赞
踩
官方如是描述:
1)
ApplicationContext
是Spring中的核心接口和容器,允许容器通过应用程序上下文环境创建、获取、管理bean。
2)在构建容器的时候,创建对象采用的策略是立即加载
的方式,即只要一读取完配置文件就立即创建配置文件中配置的对象。
ApplicationContext.publishEvent(事件机制)是Spring提供的解耦的一种方式,采用观察者设计模式
;我们可以使用 MQ或 线程池 来代替它。
- ApplicationContext中的事件处理是通过
ApplicationEvent
事件类和ApplicationListener
事件监听器接口提供的;- 事件机制的3要素:事件发布者(
ApplicationContext
)、事件(ApplicationEvent
)、事件监听器(EventListener
/ ApplicationListener);
(1)通过ApplicationContext的publishEvent()
方法将事件发布
到ApplicationListener(EventListener的子类)
/ EventListener
; 通知事件监听器处理事件;
(2)事件监听器通过实现的ApplicationListener
#onApplicationEvent()
方法处理事件
;
总结: ApplicationEvent事件 --> ApplicationContext.publishEvent()发布事件 --> 触发EventListener/ ApplicationListener监听器 --> 监听器执行内部onApplicationEvent(ApplicationEvent e)方法。
所以,只需要在容器中注册实现了ApplicationListener的Bean,当ApplicationContext发布事件时,事件会被监听器自动捕获。
(1) ApplicationContext.publishEvent 默认是同步操作
, 并非发布后不管的异步操作,发布事件后需要等 EventListener / ApplicationListener 执行完;
(2) 如果需要开启异步操作
需要在EventListener / ApplicationListener子类上增加 @Async 注解
。
Spring底层publishEvent()方法发布一个事件之后,会调用SimpleApplicationEventMulticaster#multicastEvent()
方法;
遍历所有相应EventType的ApplicationListener,然后执行每个Listener的onApplicationEvent()方法。
如果设置了线程池,监听器的执行将放在线程池中执行。
想让Spring事件异步执行时可以考虑使用线程:
// SimpleApplicationEventMulticaster
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
在配置类中手动注入SimpleApplicationEventMulticaster(beanName为:applicationEventMulticaster
),并设置线程池。
@Configuration public class EventConfig { @Bean(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME) public SimpleApplicationEventMulticaster myEventMulticaster(){ SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(); simpleApplicationEventMulticaster.setTaskExecutor(taskExecutor()); return simpleApplicationEventMulticaster; } @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(20); executor.setQueueCapacity(100); executor.setKeepAliveSeconds(300); executor.setThreadNamePrefix("thread-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } }
我们从要发布的事件、发布事件、处理事件三个方面来看。
自定义的事件只需继承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;
}
}
如果想让Spring Bean在业务过程发布指定容器事件,需要先让Bean获得ApplicationContext容器的引用,然后将指定容器事件Event交由ApplicationContext发布。
在Nacos中,UdpPushService
类中持有ApplicationContext
容器的引用:
UdpPushService
类中将ServiceChangeEvent
事件交由ApplicationContext发布:
this.applicationContext.publishEvent(new ServiceChangeEvent(this, service));
实现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
ContextRefreshedEvent是Spring内置的事件;
ApplicationContext容器初始化、refresh完后
触发该事件。
即:所有的bean被成功加载ApplicationContext容器已就绪可用。
具体体现在AbstractApplicationContext#refresh()中,在方法内部调用finishRefresh()方法,finishRefresh()方法中publishEvent
;
protected void finishRefresh() {
....
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。