spring原始碼學習筆記-初始化(五)-MessageSource/事件監聽器
轉自http://www.sandzhang.com/blog/2011/04/07/spring-study-notes-initialization-5/
refresh()方法中在上篇看完了對PostProcessors的處理,這篇繼續往下看。
注:refresh()的程式碼就不再次列舉了,請看spring原始碼中AbstractApplicationContext類。
一、initMessageSource(),這個方法是對spring的MessageSource初始化,程式碼如下:
[java] view plaincopyprint?
- ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
- //第1部分
- }
- else {
- //第2部分
- }
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
//第1部分
}
else {
//第2部分
}
- 首先獲取beanFactory物件,然後判斷是否定義了名為messageSource的localbean,如果有則執行第1部分,否則執行第2部分,分別來看兩部分程式碼
注:localbean實際上就是指查詢的時候不會去parent查詢這個bean,只從當前beanfactory去查詢,很多地方有這個就不一一註明了
第1部分:
[java] view plaincopyprint?
- 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) {
- hms.setParentMessageSource(getInternalParentMessageSource());
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Using MessageSource [" + this.messageSource + "]");
- }
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) {
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
- 第1行獲取名為messageSource的bean賦值給當前ApplicationContext物件的messageSource屬性
- 第2行判斷如果當前ApplicationContext的parent不為null;並且messageSource物件繼承了HierarchicalMessageSource介面則進行如下處理:
進行判斷如果messageSource的parentMessageSource為空,則設定為getInternalParentMessageSource()方法的返回值。getInternalParentMessageSource()方法的程式碼也很簡單
(getParent() instanceof AbstractApplicationContext) ? ((AbstractApplicationContext) getParent()).messageSource : getParent()
如果當前ApplicationContext的parent物件是AbstractApplicationContext或其子類型別則返回它的messageSource,否則直接返回其parent物件 - 最後是列印一行debug級別日誌表示當前應用的messageSource
第2部分:
[java] view plaincopyprint?- DelegatingMessageSource dms = new DelegatingMessageSource();
- dms.setParentMessageSource(getInternalParentMessageSource());
- this.messageSource = dms;
- beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
- if (logger.isDebugEnabled()) {
- logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
- "': using default [" + this.messageSource + "]");
- }
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
- 第1行建立一個DelegatingMessageSource物件dms
- 第2行類似上面,設定dms的parentMessageSource為getInternalParentMessageSource()返回值
- 第3行設定當前ApplicationContext的messageSource屬性為dms
- 第4行把這個物件註冊一個名為messageSource的單例bean
- 列印一行debut日誌表示無使用者定義messageSource,使用預設
[java] view plaincopyprint?
- 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 + "]");
- }
- }
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 + "]");
}
}
- 和messageSource的處理類似,首先取得beanFactory物件,
- 判斷如果使用者主動定義了applicationEventMulticaster的bean,則把這個bean設定給applicationEventMulticaster屬性
- 如果沒有則初始話一個預設的SimpleApplicationEventMulticaster,註冊bean並賦值給對應屬性
- 不同情況分別列印不同的日誌,原始碼中的日誌列印最好也稍微注意一下有個印象,這樣在看spring的日誌時會更清晰
三、接下來是一個模板方法onRefresh(),第一篇中提到過這個是在處理messageSource、applicationEventMulticaster等特殊bean後,普通單例bean沒初始話之前,為ApplicationContext子類提供擴充套件去處理一些類似的特殊bean。
舉個例子AbstractRefreshableWebApplicationContext、GenericWebApplicationContext、StaticWebApplicationContext中都有一個themeSource,這個就要放在這個方法裡去初始化。這個themeSource是spring的主題功能,可以實現根據不同主題載入不同資原始檔等功能。
四、上面處理了事件監聽器的管理器初始化,現在開始做時間監聽器的註冊:registerListeners(),這個方法的程式碼如下:
[java] view plaincopyprint?
- for (ApplicationListener listener : getApplicationListeners()) {
- getApplicationEventMulticaster().addApplicationListener(listener);
- }
- String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
- for (String lisName : listenerBeanNames) {
- getApplicationEventMulticaster().addApplicationListenerBean(lisName);
- }
for (ApplicationListener listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
- 上面3行是處理當前ApplicationContext中的靜態特殊監聽器集合,迴圈呼叫applicationEventMulticaster的addApplicationListener()方法註冊到applicationEventMulticaster中
- 後面的一部分首先取出所有型別為ApplicationListener的bean的name集合,然後迴圈呼叫applicationEventMulticaster的addApplicationListenerBean()方法註冊到applicationEventMulticaster中
- 注意上面兩個註冊方法的不同,分別會註冊到applicationEventMulticaster.defaultRetriever的不同集合中
本篇分別看到了messageSource、applicationEventMulticaster和applicationListener以及中間提到的主題themeSource的初始化,這裡主要介紹初始話,所以後續再對spring的這幾個功能模組做分別詳細的分析。