Spring Boot版本
org.springframework.boot
spring-boot
1.3.6.RELEASE
查阅代码会发现,事件的执行在类:SimpleApplicationEventMulticaster
代码块:
private Executor taskExecutor;
protected Executor getTaskExecutor() {
return this.taskExecutor;
}
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
设置方法:
@Bean
public SmartInitializingSingleton applicationEventMulticasterInitializer(List eventMulticasters) {
return () -> {
for (SimpleApplicationEventMulticaster eventMulticaster : eventMulticasters) {
//设置任务执行器 这样就实现了异步调用 (缺点是全局的,要么全异步,要么全同步,包括spring框架自身Listener)
eventMulticaster.setTaskExecutor(Executors.newFixedThreadPool(10));
}
};
}
通过使用SmartInitializingSingleton,对现有的SimpleApplicationEventMulticaster进行增强。
SmartInitializingSingleton:
实现该接口后,当所有单例 bean 都初始化完成以后, 容器会回调该接口的方法 afterSingletonsInstantiated。主要应用场合就是在所有单例 bean 创建完成之后,可以在该回调中做一些事情。
以下这个方法会存在问题,导致自定义的Spring Boot事件监听不到,例如:ApplicationStartedEvent、ApplicationReadyEvent
我们看到AbstractApplicationContext类中如下代码,Spring会先获取已经存在的applicationEventMulticaster bean,没有的情况下才会重新创建一个。
APPLICATION_EVENT_MULTICASTER_BEAN_NAME="applicationEventMulticaster"
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
然后想到可以自定义一个ApplicationEventMulticaster bean,让系统使用我们的ApplicationEventMulticaster
@Bean
public ApplicationEventMulticaster applicationEventMulticaster(BeanFactory beanFactory) {
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
eventMulticaster.setTaskExecutor(Executors.newFixedThreadPool(10));
return eventMulticaster;
}
但是这种方式无法覆盖Spring Boot中的ApplicationEventMulticaster变量,由于Spring Boot中的此变量是new出来的
类:EventPublishingRunListener
private final ApplicationEventMulticaster multicaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
...
// new一个出来
this.multicaster = new SimpleApplicationEventMulticaster();
...
}
private void registerApplicationEventMulticaster(ConfigurableApplicationContext context) {
// 注册到BeanFactory
context.getBeanFactory().registerSingleton(
AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
this.multicaster);
...
}
private void publishEvent(SpringApplicationEvent event) {
// 主要是这一行,Spring Boot直接使用内部变量发送事件
this.multicaster.multicastEvent(event);
}
public void started() {
// puublish ApplicationStartedEvent 事件
publishEvent(new ApplicationStartedEvent(this.application, this.args));
}
其他方法:
使用:@EnableAsync与@Async注解