一、概述
>1 ApplicationContext简述
官方如是描述:
1)ApplicationContext
是Spring中的核心接口和容器,允许容器通过应用程序上下文环境创建、获取、管理bean。
2)在构建容器的时候,创建对象采用的策略是立即加载
的方式,即只要一读取完配置文件就立即创建配置文件中配置的对象。
>2 ApplicationContext事件机制简述
ApplicationContext.publishEvent(事件机制)是Spring提供的解耦的一种方式,采用观察者设计模式
;我们可以使用 MQ或 线程池 来代替它。
- ApplicationContext中的事件处理是通过
ApplicationEvent
事件类和ApplicationListener
事件监听器接口提供的;- 事件机制的3要素:事件发布者(
ApplicationContext
)、事件(ApplicationEvent
)、事件监听器(EventListener
/ ApplicationListener);
>3 事件触发 && 监听处理过程
(1)通过ApplicationContext的publishEvent()
方法将事件发布
到ApplicationListener(EventListener的子类)
/ EventListener
; 通知事件监听器处理事件;
(2)事件监听器通过实现的ApplicationListener
#onApplicationEvent()
方法处理事件
;
总结: ApplicationEvent事件 --> ApplicationContext.publishEvent()发布事件 --> 触发EventListener/ ApplicationListener监听器 --> 监听器执行内部onApplicationEvent(ApplicationEvent e)方法。
所以,只需要在容器中注册实现了ApplicationListener的Bean,当ApplicationContext发布事件时,事件会被监听器自动捕获。
>4 注意点
(1) ApplicationContext.publishEvent 默认是同步操作
, 并非发布后不管的异步操作,发布事件后需要等 EventListener / ApplicationListener 执行完;
(2) 如果需要开启异步操作
需要在EventListener / ApplicationListener子类上增加 @Async 注解
。
二、在Nacos中的应用(事件机制的使用)
我们从要发布的事件、发布事件、处理事件三个方面来看。
>1 要发布的事件
自定义的事件只需继承ApplicationEvent
即可。
public class ServiceChangeEvent extends ApplicationEvent {
private Service service;
public ServiceChangeEvent(Object source, Service service) {
super(source);
this.service = service;
}
public Service getService() {
return service;
}
}
>2 发布事件
如果想让Spring Bean在业务过程发布指定容器事件,需要先让Bean获得ApplicationContext容器的引用,然后将指定容器事件Event交由ApplicationContext发布。
在Nacos中,UdpPushService
类中持有ApplicationContext
容器的引用:
UdpPushService
类中将ServiceChangeEvent
事件交由ApplicationContext发布:
this.applicationContext.publishEvent(new ServiceChangeEvent(this, service));
>3 处理事件
实现ApplicationListener
接口的onApplicationEvent()
方法,在该方法中做事件处理;
@Component
@SuppressWarnings("PMD.ThreadPoolCreationRule")
public class UdpPushService implements ApplicationContextAware, ApplicationListener<ServiceChangeEvent> {
@Override
public void onApplicationEvent(ServiceChangeEvent event) {
// todo 处理业务逻辑
// If upgrade to 2.0.X, do not push for v1.
if (ApplicationUtils.getBean(UpgradeJudgement.class).isUseGrpcFeatures()) {
return;
}
.......
// 发送UDP请求
udpPush(ackEntry);
.......
}
三、补充
更多内容可以请见Spring官网: https://docs.spring.io/spring-framework/docs/5.2.19.RELEASE/spring-framework-reference/core.html#context-functionality-events
>1 ContextRefreshedEvent(内置事件)
ApplicationContext容器初始化或刷新
触发该事件。此处说的初始化,是指所有的bean被成功加载,后处理的bean被检测激活,所有的singleton bean被预初始化,ApplicationContext容器已就绪可用。