Spring 事件
2022-10-20 15:48:04 0 举报
AI智能生成
Spring 事件
作者其他创作
大纲/内容
Java 事件
观察者模式
可观者对象(消息发送者)
java.util.Observable
观察者
java.util.Observer
标准化接口
事件对象(事件传输对象)
java.util.EventObject
事件监听器
java.util.EventListener
示例
Java 标准事件
EventListener
EventObject
Spring 标准化事件
Spring 事件监听器
ApplicationListener
Spring 事件传输对象
ApplicationEvent
Spring 事件发布器
ApplicationEventPublisher
Spring 事件广播器
ApplicationEventMulticaster
Spring 内建的事件
ApplicationEvent
ContextClosedEvent
上下文关闭事件
ContextRefreshEvent
上下文启动事件
ContextStartedEvent
上下文启动完成事件
ContextStoppedEvent
上下文停止事件
Spring 事件监听器使用
通过 API 的方式实现
通过注解的方式
注册SpringApplicationListener
通过ApplicationContext
applicationContext.addApplicationListener(new MyListener());
通过register注册
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(MyListener.class);
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 方法去切换同步和异步模式
转换示例
API示例
注解示例
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 监听父类事件,父类发送能收到消息,子类发送也能收到消息
解决方案:在事件监听时,监听的事件越具体越好,避免消息发送错乱。
层次性示例
0 条评论
下一页