spring源码学习笔记-初始化(五)-MessageSource/事件监听器

时间:2022-01-28 21:20:48

转自http://www.sandzhang.com/blog/2011/04/07/spring-study-notes-initialization-5/

refresh()方法中在上篇看完了对PostProcessors的处理,这篇继续往下看。

注:refresh()的代码就不再次列举了,请看spring源码中AbstractApplicationContext类。

一、initMessageSource(),这个方法是对spring的MessageSource初始化,代码如下:


[java] view plaincopyprint?
  1. ConfigurableListableBeanFactory beanFactory = getBeanFactory();  
  2. if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {  
  3.     //第1部分   
  4. }  
  5. else {  
  6.     //第2部分   
  7. }  

  • 首先获取beanFactory对象,然后判断是否定义了名为messageSource的localbean,如果有则执行第1部分,否则执行第2部分,分别来看两部分代码 
    注:localbean实际上就是指查找的时候不会去parent查找这个bean,只从当前beanfactory去查找,很多地方有这个就不一一注明了

第1部分:


[java] view plaincopyprint?
  1. this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);  
  2. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {  
  3.     HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;  
  4.     if (hms.getParentMessageSource() == null) {  
  5.         hms.setParentMessageSource(getInternalParentMessageSource());  
  6.     }  
  7. }  
  8. if (logger.isDebugEnabled()) {  
  9.     logger.debug("Using MessageSource [" + this.messageSource + "]");  
  10. }  

  • 第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?
  1. DelegatingMessageSource dms = new DelegatingMessageSource();  
  2. dms.setParentMessageSource(getInternalParentMessageSource());  
  3. this.messageSource = dms;  
  4. beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);  
  5. if (logger.isDebugEnabled()) {  
  6.     logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +  
  7.             "': using default [" + this.messageSource + "]");  
  8. }  

  • 第1行创建一个DelegatingMessageSource对象dms
  • 第2行类似上面,设置dms的parentMessageSource为getInternalParentMessageSource()返回值
  • 第3行设置当前ApplicationContext的messageSource属性为dms
  • 第4行把这个对象注册一个名为messageSource的单例bean
  • 打印一行debut日志表示无用户定义messageSource,使用默认
二、紧接着处理完messageSource的初始化后下一行代码:initApplicationEventMulticaster(),主要是对spring的事件监听器的管理器的初始话,代码如下:

[java] view plaincopyprint?
  1. ConfigurableListableBeanFactory beanFactory = getBeanFactory();  
  2. if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {  
  3.     this.applicationEventMulticaster =  
  4.             beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);  
  5.     if (logger.isDebugEnabled()) {  
  6.         logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");  
  7.     }  
  8. }  
  9. else {  
  10.     this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);  
  11.     beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);  
  12.     if (logger.isDebugEnabled()) {  
  13.         logger.debug("Unable to locate ApplicationEventMulticaster with name '" +  
  14.                 APPLICATION_EVENT_MULTICASTER_BEAN_NAME +  
  15.                 "': using default [" + this.applicationEventMulticaster + "]");  
  16.     }  
  17. }  

  • 和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?
  1. for (ApplicationListener listener : getApplicationListeners()) {  
  2.     getApplicationEventMulticaster().addApplicationListener(listener);  
  3. }  
  4.    
  5. String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.classtruefalse);  
  6. for (String lisName : listenerBeanNames) {  
  7.     getApplicationEventMulticaster().addApplicationListenerBean(lisName);  
  8. }  

  • 上面3行是处理当前ApplicationContext中的静态特殊监听器集合,循环调用applicationEventMulticaster的addApplicationListener()方法注册到applicationEventMulticaster中
  • 后面的一部分首先取出所有类型为ApplicationListener的bean的name集合,然后循环调用applicationEventMulticaster的addApplicationListenerBean()方法注册到applicationEventMulticaster中
  • 注意上面两个注册方法的不同,分别会注册到applicationEventMulticaster.defaultRetriever的不同集合中

 

本篇分别看到了messageSource、applicationEventMulticaster和applicationListener以及中间提到的主题themeSource的初始化,这里主要介绍初始话,所以后续再对spring的这几个功能模块做分别详细的分析。