鹏哥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,处理相应逻辑


分享到:


相關文章: