Spring Event是异步的吗


前言

Spring Event的使用
Spring Event原理
Spring Event如何变成异步


前言

在看上篇springboot配置文件加载源码时,发现Spring Event不一定是异步的,这和我以往的认知不太一样。技术看来不能只通过道听途说或者百度,还是要自己亲自去验证。

1.Spring Event使用

1.1 定义事件,继承ApplicationEvent

Spring Event是异步的吗

1.2 定义监听器

实现了ApplicationListener接口,用来监听事件。并交给spring管理


Spring Event是异步的吗

1.3 发布事件

Spring Event是异步的吗

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);
    }
}
先判断Event的类型,然后调用getApplicationEventMulticaster()获取事件发布器。
#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 初始化

在讲springboot源码有提到过,在完成prepareContext后,会调用refreshContext刷新上下文。这也是spring的核心所在。
#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);
    }
可以看到通过有参构造创建的SimpleApplicationEventMulticaster,并未初始化taskExecutor,errorHandler,同时这两个属性也是允许为空的。

2.2 multicastEvent

有了SimpleApplicationEventMulticaster,我们再继续跟踪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);
        }

    }
}
可以很清楚的看到,如果taskExecutor为空,那么就会同步的调用invokeListener方法。事实上默认情况下并未给taskExecutor赋值。 这和我们使用@Async注解不太一样。
然后再看一眼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就是异步了。



Spring Event是异步的吗
关注我的你,是最香哒!


原文始发于微信公众号(小李的源码图):Spring Event是异步的吗

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/145346.html

(1)
青莲明月的头像青莲明月

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!