Spring 标准化事件
Spring 事件监听器
ApplicationListener
Spring 事件传输对象
ApplicationEvent
Spring 事件发布器
ApplicationEventPublisher
Spring 事件广播器
ApplicationEventMulticaster
注册SpringApplicationListener
通过ApplicationContext
applicationContext.addApplicationListener(new MyListener());
通过register注册
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();<br> applicationContext.register(MyListener.class);
Spring 事件发布器
ApplicationEventPublisher
如何获取 ApplicationEventPublisher
通过 ApplicationEventPublisherAware 依赖注入
事件发布
applicationEventPublisher.publishEvent(new ApplicationEvent("Hello World"){});
底层委托给事件广播器来推送事件
Spring 事件广播器
ApplicationEventMulticaster
获取方式
依赖注入
依赖查找
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
具有功能
对 Listener 进行管理(增加和移除)
事件广播
同步和异步切换
同步模式
同步模式下,需要等待监听器执行完业务,事件过长的情况下,可能会导致请求失败
异步模式
如 java.util.concurrent.ThreadPoolExecutor 异步模式下,无需等待
同步与异步之间切换
通过 SimpleApplicationEventMulticaster#setTaskExecutor(java.util.concurrent.Executor) 进行模式切换
存在的问题
非基于接口契约编程, 需要从 BeanFactory 中取出 ApplicationEventMulticaster 强转成 SimpleApplicationEventMulticaster 才具有切换模式的能力
ApplicationEventMulticaster 没有提供同步和异步切换的功能,也没有提供相关的 API。只能通过强转为 SimpleApplicationEventMulticaster 并调用 setTaskExecutor 方法去切换同步和异步模式
Spring 层次性上下文事件传播
定义
存在多个 BeanFactory 存在层次性关系时,事件的推送会从先推送父类,再推送子类
处理方案
定位 Spring 事件源(ApplicationContext)进行过滤处理
解决方案:如果已经处理过就不处理,添加一个处理标识。但需要为 static 修饰,parentBeanFactory 和 currentBeanFactory 中都有实例
示例
产生的源码分析
在 publishEvent 方法处理的时候,会查询父类是否存在,如果存在,则先推送父类的事件。
Spring 4.2 Payload 事件
使用场景:简化 Spring 事件发送,关注事件源主体
发送方法:ApplicationEventPublisher#publishEvent(java.lang.Object)
注意事项
PayloadApplicationEvent 本身允许扩展,但扩展的时候需要带上泛型,否则会报错
根据 java doc 描述,PayloadApplicationEvent 是内部使用的 API,但是,内部使用的地方缺很少
在 ApplicationEventPublisher#publishEvent(Object event); 方法中,底层会将 event 对象包装成 PayloadApplicationEvent 对象,没必要再去封装 PayloadApplicationEvent 对象。
使用示例
自定义 Spring 事件
扩展 org.springframework.context.ApplicationEvent
实现 org.springframework.context.ApplicationListener
注册 org.springframework.context.ApplicationListener
Spring 3 存在的 bug
当一个类同时实现了 ApplicationEventPublisherAware、BeanPostProcessor 两个接口时,会导致事件发送时产生空指针问题
流程图及解决方案
Spring 4.1 事件异常处理
错误处理接口 - org.springframework.util.ErrorHandler
源码分析
使用示例
Spring 按照指定类型发送事件
getApplicationListeners 方法分析,首先根据 ResolvableType 去构建缓存 key, 如果缓存 key 能查找监听器,则直接返回,如果没有,则重新构建缓存
ApplicationEvent 存在继承,消息发送问题
Listener 监听子类事件,父类发送则收不到消息,子类发送可以收到消息
Listener 监听父类事件,父类发送能收到消息,子类发送也能收到消息
解决方案:在事件监听时,监听的事件越具体越好,避免消息发送错乱。
层次性示例