鵬哥SpringSession三部曲之三 SpringSession Event 詳解

鵬哥之前也沒有Spring Session的基礎,完全是從零開始,在搜索了無數教程和一步一步的跟蹤代碼之後,慢慢摸清了一些門道,分享給大家。知識點很多很雜,思路和流程主要參考一網友懷瑾握瑜的博客(https://www.cnblogs.com/lxyit/category/1303872.html),因為作者的思路還算清晰,鵬哥受益匪淺。

先來看下Session事件抽象UML類圖,整體掌握事件之間的依賴關係。

鵬哥SpringSession三部曲之三 SpringSession Event 詳解

Session Event最頂層是ApplicationEvent,即Spring上下文事件對象。由此可以看出Spring-Session的事件機制是基於Spring上下文事件實現。

抽象的AbstractSessionEvent事件對象提供了獲取Session(這裡的是指Spring Session的對象)和SessionId。

基於事件的類型,分類為:

  • Session創建事件
  • Session刪除事件
  • Session過期事件

事件對象只是對事件本身的抽象,描述事件的屬性,如:

  • 獲取事件產生的源:getSource獲取事件產生源
  • 獲取相應事件特性:getSession/getSessoinId獲取時間關聯的Session

事件的觸發機制

鵬哥SpringSession三部曲之三 SpringSession Event 詳解

  • ApplicationEventPublisher實現用於發佈Spring上下文事件ApplicationEvent
  • ApplicationListener實現用於監聽Spring上下文事件ApplicationEvent
  • ApplicationEvent抽象上下文事件

Session事件的流程實現如下:

鵬哥SpringSession三部曲之三 SpringSession Event 詳解

上圖展示了Spring-Session事件流程圖,事件源來自於Redis鍵空間通知,在spring-data-redis項目中抽象MessageListener監聽Redis事件源,然後將其傳播至spring應用上下文發佈者,由發佈者發佈事件。在spring上下文中的監聽器Listener即可監聽到Session事件。

因為兩者是Spring框架提供的對Spring的ApplicationEvent的支持。Session Event基於ApplicationEvent實現,必然也有其相應發佈者和監聽器的的實現。

Spring-Session中的RedisSession的SessionRepository是RedisOperationSessionRepository。所有關於RedisSession的管理操作都是由其實現,所以Session的產生源是RedisOperationSessionRepository。

在RedisOperationSessionRepository中持有ApplicationEventPublisher對象用於發佈Session事件。

但是該ApplicationEventPublisher是空實現,實際實現是在應用啟動時由Spring-Session自動配置。在spring-session-data-redis模塊中RedisHttpSessionConfiguration中有關於創建RedisOperationSessionRepository Bean時將調用set方法將ApplicationEventPublisher配置。

以上部分探索了Session事件的發佈者和監聽者,但是核心事件的觸發發佈則是由Redis的鍵空間通知機制觸發,當有Session創建/刪除/過期時,Redis鍵空間會通知Spring-Session應用。

RedisOperationsSessionRepository實現spring-data-redis中的MessageListener接口。

該監聽器即用來監聽redis發佈的消息。RedisOperationsSessionRepositorys實現了該Redis鍵空間消息通知監聽器接口

Session創建事件的觸發

鵬哥SpringSession三部曲之三 SpringSession Event 詳解

  1. 由RedisOperationSessionRepository向Redis指定通道
  2. {sessionId}發佈一個message
  3. MessageListener的實現RedisOperationSessionRepository監聽到Redis指定通道
  4. {sessionId}的消息
  5. 將其傳播至ApplicationEventPublisher
  6. ApplicationEventPublisher發佈SessionCreateEvent
  7. ApplicationListener監聽SessionCreateEvent,執行相應邏輯

Session刪除事件的觸發

鵬哥SpringSession三部曲之三 SpringSession Event 詳解

  1. 由RedisOperationSessionRepository刪除Redis鍵空間中的指定Session的過期鍵,Redis鍵空間會向__keyevent *:del的channel發佈刪除事件消息
  2. MessageListener的實現RedisOperationSessionRepository監聽到Redis指定通道__keyevent *:del的消息
  3. 將其傳播至ApplicationEventPublisher
  4. ApplicationEventPublisher發佈SessionDeleteEvent
  5. ApplicationListener監聽SessionDeleteEvent,執行相應邏輯

Session失效事件的觸發

Session的過期事件流程比較特殊,因為Redis的鍵空間通知的特殊性,Redis鍵空間通知不能保證過期鍵的通知的及時性。

鵬哥SpringSession三部曲之三 SpringSession Event 詳解

  1. RedisOperationsSessionRepository中有個定時任務方法每整分運行訪問整分Session過期鍵集合中的過期sessionId,如:spring:session:expirations:1439245080000。觸發Redis鍵空間會向__keyevent *:expired的channel發佈過期事件消息
  2. MessageListener的實現RedisOperationSessionRepository監聽到Redis指定通道__keyevent *:expired的消息
  3. 將其傳播至ApplicationEventPublisher
  4. ApplicationEventPublisher發佈SessionDeleteEvent
  5. ApplicationListener監聽SessionDeleteEvent,執行相應邏輯

總結

至此Spring-Session的Session事件通知模塊就已經很清晰:

  • Redis鍵空間Session事件源:Session創建通道/Session刪除通道/Session過期通道
  • Spring-Session中的RedisOperationsSessionRepository消息監聽器監聽Redis的事件類型
  • RedisOperationsSessionRepository負責將其傳播至ApplicationEventPublisher
  • ApplicationEventPublisher將其包裝成ApplicationEvent類型的Session Event發佈
  • ApplicationListener監聽Session Event,處理相應邏輯


分享到:


相關文章: