天天看點

Spring容器重新整理—08-initApplicationEventMulticaster

作者:當年三歲半
Spring容器重新整理—08-initApplicationEventMulticaster

這次的内容是上圖中的第08步。

前言

先來看看前面幾篇文章都做了什麼:

`01-prepareRefresh()`: `earlyApplicationListeners`、`applicationListeners` 、`initPropertySources()`、`validateRequiredProperties`
`02-obtainFreshBeanFactory()`: `refreshBeanFactory`
`03-prepareBeanFactory()`: `ignoreDependencyInterface`、`setBeanExpressionResolver`、`registerResolvableDependency`、`Environment`
`04-postProcessBeanFactory()`: 具體實作類的特殊邏輯(`Servlet` 等)
`05-invokeBeanFactoryPostProcessors()`: 可能發生的對 `BeanFactory/BeanDefinitionRegistry` 的修改操作
`06-registerBeanPostProcessors()`: 所有的 `BeanPostProcessor` 已經被執行個體化并且注冊到了 `BeanFactory` 中
`07-initMessageSource()`: `MessageSource` 已經就緒了,可以支援國際化(`I18N`)資源處理了           

上一個步驟是初始化 MessageSource 以支援 I18N, 依然是在為 Bean 的建立做準備工作。

本文要介紹的 initApplicationEventMulticaster() 依然是在給 Bean 的建立做準備工作。本文的内容也是非常非常簡單。

initApplicationEventMulticaster() 就是初始化 ApplicationEventMulticaster,那麼什麼是 ApplicationEventMulticaster 呢?

前置知識

先來了解下 ApplicationEventMulticaster、ApplicationContext 和 ApplicationEventPublisher 這三個元件的關系。

Spring容器重新整理—08-initApplicationEventMulticaster

ApplicationEventMulticaster

ApplicationEventMulticaster 是 spring 中事件功能的重要元件。可以通過他注冊/删除監聽器、釋出事件。接口聲明如下:

public interface ApplicationEventMulticaster {

    void addApplicationListener(ApplicationListener<?> listener);

    // 通過 beanName 添加監聽器,避免過早初始化 Bean
    void addApplicationListenerBean(String listenerBeanName);

    void removeApplicationListener(ApplicationListener<?> listener);

    void removeApplicationListenerBean(String listenerBeanName);

    void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate);

    void removeApplicationListenerBeans(Predicate<String> predicate);

    void removeAllListeners();

    // 釋出事件的接口
    void multicastEvent(ApplicationEvent event);

    // 釋出事件的接口
    void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);

}           

SimpleApplicationEventMulticaster

再來看看 ApplicationEventMulticaster 的一個簡單實作。

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    @Nullable
    private Executor taskExecutor;

    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, resolveDefaultEventType(event));
    }

    // 省略其他代碼。。。

    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor();
        // 擷取到對目前事件感興趣的 `ApplicationListener`
        // 挨個回調: 也就是監聽器被回調了
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }
}           

如果你給了他一個線程池,那他就使用線程池異步釋出事件,否則就在目前調用線程上釋出事件。

ApplicationEventPublisher

如果隻是要釋出事件的話,直接使用 ApplicationEventPublisher 接口就可以了,沒必要使用 ApplicationContext。

public interface ApplicationEventPublisher {

    void publishEvent(Object event);

}           

其實 ApplicationContext 就繼承了 ApplicationEventPublisher,那麼 ApplicationContext 的是怎麼實作事件的釋出的呢?

在 ApplicationContext 的實作中,實際上是委托給 ApplicationEventMulticaster 去釋出事件的。

比如 AbstractApplicationContext,就是将事件的釋出委托給了内部維護的一個 ApplicationEventMulticaster。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {

    @Nullable
    private ApplicationEventMulticaster applicationEventMulticaster;

    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        Assert.notNull(listener, "ApplicationListener must not be null");
        if (this.applicationEventMulticaster != null) {
            this.applicationEventMulticaster.addApplicationListener(listener);
        }
        this.applicationListeners.add(listener);
    }

    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        // 省略其他代碼
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
        // 省略其他代碼
    }
}           

initApplicationEventMulticaster

現在看看容器重新整理的第 8 步的源碼:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {

    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

    @Nullable
    private ApplicationEventMulticaster applicationEventMulticaster;

    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 1. 如果目前 BeanFactory 中已經有了名為 `applicationEventMulticaster`  的 Bean
        // 就給this.applicationEventMulticaster指派
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isTraceEnabled()) {
                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        // 2. 如果目前 BeanFactory 中還沒有名為 `applicationEventMulticaster` 的 Bean
        else {
            // new 一個 SimpleApplicationEventMulticaster 類型的 ApplicationEventMulticaster 實作
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            // 剛剛 new 出來的對象注冊到 BeanFactory 中
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                        "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
            }
        }
    }
}