前言
Spring Event如何变成异步
前言
在看上篇springboot配置文件加载源码时,发现Spring Event不一定是异步的,这和我以往的认知不太一样。技术看来不能只通过道听途说或者百度,还是要自己亲自去验证。
1.Spring Event使用
1.1 定义事件,继承ApplicationEvent
1.2 定义监听器
实现了ApplicationListener接口,用来监听事件。并交给spring管理
1.3 发布事件
2.SpringEvent原理
本篇基于springboot 2.5.14版本分析。
直接看applicationContext.publishEvent
#AbstractApplicationContext
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
}
#AbstractApplicationContext
private ApplicationEventMulticaster applicationEventMulticaster;
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
if (this.applicationEventMulticaster == null) {
throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
"call 'refresh' before multicasting events via the context: " + this);
}
return this.applicationEventMulticaster;
}
最后调用multicastEvent方法发布事件。
那么这个ApplicationEventMulticaster 是什么时候注入的?
2.1 ApplicationEventMulticaster 初始化
#AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//初始化beanfactor
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// beanFactory赋值
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//空实现,提供子类覆盖的额外处理,即子类处理自定义的beanFactorypostProcess
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//增强beanFactory功能如自动装配等
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//创建注册beanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//国际化处理
initMessageSource();
// Initialize event multicaster for this context.
//初始化多播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 初始化web服务器等bean
onRefresh();
// Check for listener beans and register them.
//将所有的ApplicationListener添加到事件多播器中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//实例化所有非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//启动servelt服务器等
finishRefresh();
}
可以看到在国际化处理之后会调用initApplicationEventMulticaster方法来初始化多播器
#AbstractApplicationContext
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);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
如果本地有applicationEventMulticaster,就使用自定义的applicationEventMulticaster;如果没有,就会创建默认的SimpleApplicationEventMulticaster放入容器。
我们接着看SimpleApplicationEventMulticaster
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
@Nullable
private volatile Log lazyLogger;
/**
* Create a new SimpleApplicationEventMulticaster.
*/
public SimpleApplicationEventMulticaster() {
}
/**
* Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
*/
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
setBeanFactory(beanFactory);
}
2.2 multicastEvent
#SimpleApplicationEventMulticaster
/**
* Return the current task executor for this multicaster.
*/
@Nullable
protected Executor getTaskExecutor() {
return this.taskExecutor;
}
@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);
}
}
}
然后再看一眼invokeListener方法,最后会调doInvokeListener方法
#SimpleApplicationEventMulticaster
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
}
这就是我们监听器重写的方法了。
所以默认情况下,SpringEvent是同步的,并非异步,它主要是用来解耦。
3.SpringEvent如何变成异步
#AbstractApplicationContext
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);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
上面分析spring的refresh源码时有看到,如果我们本地自定义了ApplicationEventMulticaster,就不会使用默认的了。
所以我们可以自定义ApplicationEventMulticaster来实现异步。
这样我们使用Spring Event就是异步了。

原文始发于微信公众号(小李的源码图):Spring Event是异步的吗
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/145346.html