【spring源碼分析】spring啓動流程(七):國際化與事件處理

注:本系列源碼分析基於spring 5.2.2.RELEASE,本文的啓動流程針對於annotation註解方式,gitee倉庫鏈接:spring-framework.

接上文,我們繼續分析spring的啓動流程。

7. 國際化: initMessageSource()

這個方法是用來初始化MessageSource的,內容如下:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {

    ...

    /**
     * 初始化 MessageSource
     */
    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 如果beanFactory中存在MessageSource,設置其 ParentMessageSource
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(
                    MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    // 設置ParentMessageSource
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
        }
        // 如果beanFactory中不存在MessageSource,就 創建-設置-註冊
        else {
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            // 設置ParentMessageSource
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        }
    }

    /**
     * 返回父容器的 messageSource
     */
    @Nullable
    protected MessageSource getInternalParentMessageSource() {
        return (getParent() instanceof AbstractApplicationContext ?
                ((AbstractApplicationContext) getParent()).messageSource : getParent());
    }

    ...
}

可以看到,整個方法主要是操作MessageSource,主要邏輯爲:如果已經存在MessageSource了,就設置一些屬性;否則就創建MessageSource,並設置些 屬性,最後註冊到beanFactory中。

關於MessageSource的具體作用,本文就不展開了。

8. 初始化事件廣播器:initApplicationEventMulticaster()

AbstractApplicationContext#initApplicationEventMulticaster代碼如下:

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,主要就是用來廣播事件的,更多關於事件的內容,可以參考spring探祕之spring 事件機制.

9. 擴展點:onRefresh()

AbstractApplicationContext#onRefresh是spring提供的一個擴展點,方法並無內容:

protected void onRefresh() throws BeansException {

}

如果需要處理特定的操作,可以在子類中實現。

當前使用的ApplicationContextAnnotationConfigApplicationContext,並無onRefresh()方法,就不過多分析了。

10. 註冊事件監聽器:registerListeners()

AbstractApplicationContext#registerListeners 相關代碼如下:

AbstractApplicationContext

/** 這裏就是用來存放監聽器的 */
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

/** 返回當前所有的監聽器 */
public Collection<ApplicationListener<?>> getApplicationListeners() {
    return this.applicationListeners;
}

/**
 * 添加監聽器
 */
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 registerListeners() {
    // 先添加手動set的一些監聽器
    // getApplicationListeners() 獲取的監聽器基本是通過調用 addApplicationListener(...) 添加的
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // 獲取取到監聽器的名稱,設置到廣播器
    // 此時獲取的監聽器是從 beanFactory 中獲取的,即是spring通過包掃描得到的
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
    // 如果存在早期應用事件,廣播
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            //  廣播早期事件
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

這個方法的流程大致如下:

  1. 添加AbstractApplicationContext#applicationListeners中的監聽器到ApplicationEventMulticaster
  2. beanFactory獲取監聽器的beanName,添加到ApplicationEventMulticaster
  3. 如果有早期事件,就進行廣播

關於spring的事件,本文並不打算展開,如果想了解更多,可參考spring探祕之spring 事件機制.

本文的分析就到這裏了。


本文原文鏈接:https://my.oschina.net/funcy/blog/4892120 ,限於作者個人水平,文中難免有錯誤之處,歡迎指正!原創不易,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

本系列的其他文章

【spring源碼分析】spring源碼分析系列目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章