spring初始化

很多人看开源框架源代码的时候都不知道从哪里入手,我这里推荐一个最简单的办法,写一个最简单的应用的例子,然后根据这个应用一点一点查看在源码中的运行步骤,这样就能对框架有一个基本的了解,有了这个基本的认识,再去针对不同模块扩展开来仔细研究。
 
本系列主要是学习spring的源码,首先是最简单的使用例子:
1
2
3
ApplicationContext ctx = new  ClassPathXmlApplicationContext(
                 "spring-config.xml" );
FooService foo = (FooService) ctx.getBean( "FooService" );

我们看第一行初始化了一个ClassPathXmlApplicationContext对象,

注:也可以用FileSystemXmlApplicationContext来加载,两者的区别只是查找配置文件的起始路径不同,一个以classpath为当前路径,一个是直接用文件系统的当前路径,内部没有太大区别。

注2:web工程大家都知道我们配置了ContextLoaderListener,这里暂时不做介绍,后面会有专门的分析,起始主题流程都差不多,详情请参见:从源码看Spring在web工程中的初始化。

请看下面的构造方法,参数是spring配置文件在classpath中的全路径名:

?
1
2
3
public  ClassPathXmlApplicationContext(String configLocation) throws  BeansException {
     this ( new  String[] {configLocation}, true , null );
}

可以看到里面调用了另外一个构造方法(如下),其中传递了两个默认参数refresh=true立即刷新,parent=null继承为空,并且把配置文件封装为了一个String数组,这里主要是因为spring是支持多个配置文件的

?
1
2
3
4
5
6
7
8
9
public  ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
             throws  BeansException {
  
     super (parent);
     setConfigLocations(configLocations);
     if  (refresh) {
         refresh();
     }
}

我们看这个构造方法的代码:

  • 首先调用了父类的构造函数
  • 调用setConfigLocations设置配置文件位置信息(代码如下)
  • 判断如果refresh为true则调用refresh()方法,refresh方法在AbstractApplicationContext中

setConfigLocations代码:
很简单,主要是检验是否传入参数为空然后赋值给configLocations属性,不过其中有两个小特点可以注意一下:

  1. 并没有直接把传入参数locations直接赋值给属性,而是new了一个String数组,然后循环赋值,这里主要是出于安全考虑避免外面传入的字符串数组变化影响spring内部
  2. 可以看到赋值前有调用了一下resolvePath方法,这个方法实现了一些系统变量的替换,例如路径里可以使用${}加载系统变量值
1
2
3
4
5
6
7
8
9
10
11
12
public  void  setConfigLocations(String[] locations) {
     if  (locations != null ) {
         Assert.noNullElements(locations,
                 "Config locations must not be null" );
         this .configLocations = new  String[locations.length];
         for  ( int  i = 0 ; i < locations.length; i++) {
             this .configLocations[i] = resolvePath(locations[i]).trim();
         }
     } else  {
         this .configLocations = null ;
     }
}

 

下面看refresh刷新方法,这个刷新方法主要是从配置文件加载bean配置的过程,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public  void  refresh() throws  BeansException, IllegalStateException {
     // 整个刷新过程是同步的
     synchronized  ( this .startupShutdownMonitor) {
         // 刷新前的准备工作
         prepareRefresh();
         // 关闭释放旧的beanFactory创建新的beanFactory,读取配置文件等
         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
         // 对beanFactory进行一些基本的初始化
         prepareBeanFactory(beanFactory);
  
         try  {
             // 下面两行主要用户扩展,处理所有已注册的BeanFactoryPostProcessor,实现在已经加载配置但未初始化bean时对配置进行修改
             postProcessBeanFactory(beanFactory);
             invokeBeanFactoryPostProcessors(beanFactory);
             // 处理所有已注册的BeanPostProcessor,主要用于扩展,实现bean初始化前后的一些定制操作
             registerBeanPostProcessors(beanFactory);
  
             // 初始化消息源bean
             initMessageSource();
             // 初始化事件监听器集,也有人叫事件监听器的注册表,所有的事件监听器都在这个bean里进行管理
             initApplicationEventMulticaster();
             // 主要用于扩展,实现一些特殊bean的初始化,时间点是类似消息源事件监听器集等特殊bean初始化后,普通的bean初始化前
             onRefresh();
             // 注册监听器
             registerListeners();
             // 初始化其余的非延迟加载的单例bean
             finishBeanFactoryInitialization(beanFactory);
  
             // 刷新完成调用LifecycleProcessor的onRefresh方法,并且发布ContextRefreshedEvent事件
             finishRefresh();
         } catch  (BeansException ex) {
             // 销毁已经创建的单例bean
             destroyBeans();
             // 重新设置active标记
         cancelRefresh(ex);
             throw  ex;
         }
     }
}

上面是一个spring初始化的基本流程框架,后面几篇将陆续对其中每一个方法进行详细的分析

 

上篇结束的地方简单介绍了一下refresh()方法,现在我们具体分析一下它的代码细节:

1.首先可以看到整个refresh()的代码都是同步的,对应的同步对象是startupShutdownMonitor,我们看一下startupShutdownMonitor引用的地方,可以知道,只有在refresh()和close()两个方法里用到,说明这个锁是用来同步applicationContext的刷新和销毁的。

2.同步代码块的第一行是prepareRefresh()方法,代码如下:

?
1
2
3
4
5
6
7
8
9
protected  void  prepareRefresh() {
     this .startupDate = System.currentTimeMillis();
     synchronized  ( this .activeMonitor) {
         this .active = true ;
     }
     if  (logger.isInfoEnabled()) {
         logger.info( "Refreshing "  + this );
     }
}

这个方法也很简单

  1. 首先设置startupDate为系统当前毫秒数,代表当前applicationContext的创建时间;
  2. 设置active为true,代表当前applicationContext是活动的,可以看到对active的赋值操作是同步的,同步对象为activeMonitor,查看active的引用点,可以看到所有对 active的操作都是同步在activeMonitor下的,在调用cancelRefresh()和doClose()两个方法的时候会把它设置为false,其中cancelRefresh()代表中止refresh,doClose()则是当前applicationContext的关闭销毁方法
  3. 最后是日志的打印,info级别,我这里要说的一点是后面直接+this,代表会调用toString方法,AbstractApplicationContext重写了toString,大概格式是displayName+startup+parent displayName

3.接着是这一行:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(),obtainFreshBeanFactory代码如下:

?
1
2
3
4
5
6
7
8
protected  ConfigurableListableBeanFactory obtainFreshBeanFactory() {
     refreshBeanFactory();
     ConfigurableListableBeanFactory beanFactory = getBeanFactory();
     if  (logger.isDebugEnabled()) {
         logger.debug( "Bean factory for "  + getDisplayName() + ": "  + beanFactory);
     }
     return  beanFactory;
}

第一行调用refreshBeanFactory(),我们先跳过这行看下面,调用了getBeanFactory()获得beanFactory对象然后返回这个对象,看getBeanFactory()的代码可以看到,是做了一个同步,然后取出当前对象里的beanFactory,同步锁是beanFactoryMonitor:

注:refreshBeanFactory()和getBeanFactory()方法在AbstractRefreshableApplicationContext类里面,关于ApplicationContext的类结构我会在另外一篇文章里做专门介绍,请看:ApplicationContext的类继承结构及框架图

?
1
2
3
4
5
6
7
8
9
public  final  ConfigurableListableBeanFactory getBeanFactory() {
     synchronized  ( this .beanFactoryMonitor) {
         if  ( this .beanFactory == null ) {
             throw  new IllegalStateException( "BeanFactory not initialized or already closed - "  +
                     "call 'refresh' before accessing beans via the ApplicationContext" );
         }
         return  this .beanFactory;
     }
}

如果beanFactory为空则会抛出异常,其实一开始beanFactory肯定是null的,beanFactory的创建就是在refreshBeanFactory()方法中,下面我们看它的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected  final  void  refreshBeanFactory() throws  BeansException {
     if  (hasBeanFactory()) {
         destroyBeans();
         closeBeanFactory();
     }
     try  {
         DefaultListableBeanFactory beanFactory = createBeanFactory();
         beanFactory.setSerializationId(getId());
         customizeBeanFactory(beanFactory);
         loadBeanDefinitions(beanFactory);
         synchronized  ( this .beanFactoryMonitor) {
             this .beanFactory = beanFactory;
         }
     }
     catch  (IOException ex) {
         throw  new ApplicationContextException( "I/O error parsing bean definition source for " + getDisplayName(), ex);
     }
}

前面3行代码首先判断是否hasBeanFactory(),如果存在则调用destroyBeans()以及closeBeanFactory():

  • hasBeanFactory()是在判断属性beanFactory是否为空,当然同上面一样beanFactory的操作是同步的,同步对象是beanFactoryMonitor。
  • destroyBeans()方法只有一行代码:getBeanFactory().destroySingletons(),调用了beanFactory对象的destroySingletons()方法来销毁所有单例bean。(后面还会用到这个方法,放到后面详细介绍)
  • closeBeanFactory()和上面一样,依旧是同步的情况下处理beanFactory属性,首先调用setSerializationId(null),然后把beanFactory属性设置为null。

接下来后面的代码是一个创建beanFactory的过程:

  • 调用createBeanFactory()方法创建一个beanFactory对象:
    查看方法代码可以看到创建的是一个DefaultListableBeanFactory对象,参数parent传递的方法getInternalParentBeanFactory()返回的结果,getInternalParentBeanFactory()方法的代码为:
    (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent()
    如果当前applicationContext对象的parent是ConfigurableApplicationContext类的实例则返回当前对象的parent的beanFactory对象,否则直接返回当前对象的parent。
     
  • 将当前对象的id属性作为参数调用为beanFactory对象的setSerializationId()方法,我们这里看下这个方法的代码:
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public  void  setSerializationId(String serializationId) {
         if  (serializationId != null ) {
             serializableFactories.put(serializationId,
                     new  WeakReference<DefaultListableBeanFactory>( this ));
         } else  if  ( this .serializationId != null ) {
             serializableFactories.remove( this .serializationId);
         }
         this .serializationId = serializationId;
    }
    首先,输入参数如果不为空执行(1),否则再判断如果当前对象的属性serializationId不为空,执行(2)
    (1)在serializableFactories里加入一组值:键为serializationId,值为当前对象的弱引用
    (2)从serializableFactories中移除键为当前对象属性serializationId的对象,也就是以前存入的当前对象的弱引用
    (3)设置属性serializationId为输入参数
     
  • customizeBeanFactory()方法的代码:
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    protected  void  customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
         if  ( this .allowBeanDefinitionOverriding != null ) {
             beanFactory.setAllowBeanDefinitionOverriding( this .allowBeanDefinitionOverriding);
         }
         if  ( this .allowCircularReferences != null ) {
             beanFactory.setAllowCircularReferences( this .allowCircularReferences);
         }
         beanFactory.setParameterNameDiscoverer( new LocalVariableTableParameterNameDiscoverer());
         beanFactory.setAutowireCandidateResolver( new QualifierAnnotationAutowireCandidateResolver());
    }
    如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性,此属性的含义:是否允许覆盖同名称的不同定义的对象
    如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性,此属性的含义:是否允许bean之间循环引用
    设置beanFactory的parameterNameDiscoverer属性为一个新的LocalVariableTableParameterNameDiscoverer对象,主要用asm解析class文件
    设置beanFactory的parameterNameDiscoverer属性为一个新的QualifierAnnotationAutowireCandidateResolver对象,主要用于自动装配的处理
     
  • loadBeanDefinitions()方法的代码:
    ?
    1
    2
    3
    4
    5
    6
    7
    protected  void  loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
         XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
         beanDefinitionReader.setResourceLoader( this );
         beanDefinitionReader.setEntityResolver( new  ResourceEntityResolver( this ));
         initBeanDefinitionReader(beanDefinitionReader);
         loadBeanDefinitions(beanDefinitionReader);
    }
    第1行创建XmlBeanDefinitionReader对象
    第2行设置beanDefinitionReader的resourceLoader属性为当前对象
    第3行设置beanDefinitionReader的entityResolver属性为一个新的ResourceEntityResolver对象,输入参数resourceLoader为当前对象,这个数要是用来解析xml的
    第4行设置beanDefinitionReader的validationMode以及namespaceAware,参数是当前对象的validating属性,主要用于xml校检
    最后一行是做了xml配置文件的读取,就不做详细描述了,有个细节是会循环加载configResources、configLocations两个里面的文件
     
  • 接着是同步操作beanFactory,把创建的beanFactory对象赋值给当前ApplicationContext的beanFactory属性

refresh()方法中在上篇obtainFreshBeanFactory()方法创建了beanfactory对象,之后的代码就开始是对beanFactory对象的一些处理,BeanFactory相关的一些内容也是spring的核心内容。

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

一、首先是prepareBeanFactory(beanFactory),主要是做了一些beanFactory的初始化工作,因为这个方法比较长,我们分成4部分来看,

第1部分代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver( new  StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar( new  ResourceEditorRegistrar( this ));
beanFactory.addBeanPostProcessor( new  ApplicationContextAwareProcessor( this ));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware. class );
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware. class );
beanFactory.ignoreDependencyInterface(MessageSourceAware. class );
beanFactory.ignoreDependencyInterface(ApplicationContextAware. class );
beanFactory.registerResolvableDependency(BeanFactory. class , beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader. class , this );
beanFactory.registerResolvableDependency(ApplicationEventPublisher. class , this );
beanFactory.registerResolvableDependency(ApplicationContext. class , this );
  • 第1行设置beanFactory的classLoader为当前context的classLoader
  • 第2行设置beanFactory的表达式语言处理器,spring3增加了表达式语言的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值。
  • 第3行为beanFactory增加了一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具,以后再做详细分析。
  • 第4行添加了一个处理aware相关接口的beanPostProcessor扩展,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置处理方法实现aware相关接口的功能,aware接口是用来给bean注入一些资源的接口,例如实现BeanFactoryAware的Bean在初始化后,Spring容器将会注入BeanFactory的实例相应的还有ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等。
  • 第5-8行设置了几个忽略自动装配的接口,默认只有BeanFactoryAware被忽略,其他的都要自行设置,这里设置了ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware和ApplicationContextAware。
  • 第9-12行设置了几个自动装配的特殊规则,如果是BeanFactory类型,则注入beanFactory对象,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext类型则注入当前对象(applicationContext对象)。

第2部分代码:

?
1
2
3
4
if  (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
     beanFactory.addBeanPostProcessor( new  LoadTimeWeaverAwareProcessor(beanFactory));
     beanFactory.setTempClassLoader( new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
  • 这部分判断是否定义了名为loadTimeWeaver的bean,如果定义了则添加loadTimeWeaver功能的beanPostProcessor扩展,并且创建一个临时的classLoader来让其处理真正的bean。spring的loadTimeWeaver主要是通过 instrumentation 的动态字节码增强在装载期注入依赖。具体这部分还没有很好的理解,暂时标记一下以后再专门研究看看。

第3部分代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if  (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
     Map systemProperties;
     try  {
         systemProperties = System.getProperties();
     } catch  (AccessControlException ex) {
         systemProperties = new  ReadOnlySystemAttributesMap() {
             protected  String getSystemAttribute(String propertyName) {
                 try  {
                     return  System.getProperty(propertyName);
                 } catch  (AccessControlException ex) {
                     if  (logger.isInfoEnabled()) {
                         logger.info( "Not allowed to obtain system property [" + propertyName + "]: "  +
                                 ex.getMessage());
                     }
                     return  null ;
                 }
             }
         };
     }
     beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
}
  • 这部分首先判断是否定义了名为systemProperties的bean,如果没有则加载系统获取当前系统属性System.getProperties()并注册为一个单例bean。假如有AccessControlException权限异常则创建一个ReadOnlySystemAttributesMap对象,可以看到创建时重写了getSystemAttribute()方法,查看ReadOnlySystemAttributesMap的代码可以得知在调用get方法的时候会去调用这个方法来获取key对应的对象,当获取依旧有权限异常AccessControlException的时候则返回null。

第4部分代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if  (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
     Map<String,String> systemEnvironment;
     try  {
         systemEnvironment = System.getenv();
     } catch  (AccessControlException ex) {
         systemEnvironment = new  ReadOnlySystemAttributesMap() {
             protected  String getSystemAttribute(String variableName) {
                 try  {
                     return  System.getenv(variableName);
                 } catch  (AccessControlException ex) {
                     if  (logger.isInfoEnabled()) {
                         logger.info( "Not allowed to obtain system environment variable [" + variableName + "]: "  +
                                 ex.getMessage());
                     }
                     return  null ;
                 }
             }
         };
     }
     beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
}
  • 这部分和上面一部分类似,只不过由系统属性改为了系统环境变量,异常处理方式等也和上面一部分一样。这两部分都是为spring内部提供系统信息的支撑bean。

 

二、prepareBeanFactory()方法调用之后,是一个try-catch代码块,如果有BeanException异常产生则会停止refresh并且销毁已创建的资源,现在看代码块里的第一行postProcessBeanFactory(beanFactory)

postProcessBeanFactory()方法,默认方法体是空的,主要是用来扩展beanfactory的,扩展点是在bean等配置都已经加载但还没有进行实例化的时候。

例如上面说到的aware相关接口自动装配设置,假如是web项目,使用的是spring的webApplicationcontext,这时需要一些ServletContextAware相关的自动装配忽略及配置等,就需要在webApplicationContext里重写这个方法来实现相应功能。

 

refresh()方法中在上篇看到了postProcessBeanFactory(beanFactory),这篇继续往下看。

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

一、invokeBeanFactoryPostProcessors(beanFactory),这个方法从名字就可以看出是在调用BeanFactoryProcessor,代码也比较长,分成几部分来看。

第1部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Set<String> processedBeans = new  HashSet<String>();
if  (beanFactory instanceof  BeanDefinitionRegistry) {
     BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
     List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
     List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
             new  LinkedList<BeanDefinitionRegistryPostProcessor>();
     for  (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
         if  (postProcessor instanceof  BeanDefinitionRegistryPostProcessor) {
             BeanDefinitionRegistryPostProcessor registryPostProcessor =
                     (BeanDefinitionRegistryPostProcessor) postProcessor;
             registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
             registryPostProcessors.add(registryPostProcessor);
         }
         else  {
             regularPostProcessors.add(postProcessor);
         }
     }
     Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
             beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor. class , true , false );
     List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
             new  ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
     OrderComparator.sort(registryPostProcessorBeans);
     for  (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
         postProcessor.postProcessBeanDefinitionRegistry(registry);
     }
     invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
     invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
     invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
     processedBeans.addAll(beanMap.keySet());
}
else  {
     invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
}
  • 首先创建一个HashSet变量processedBeans,接着是个判断,如果beanFactory类型实现了BeanDefinitionRegistry接口,强转beanFactory对象为BeanDefinitionRegistry类型变量registry,创建两个LinkedList变量regularPostProcessors用来存储普通PostProcessor;registryPostProcessors用来存储一些用来对bean定义的注册信息进行处理的PostProcessor。
  • 7-17行循环所有applicationContext中已经注册的BeanFactoryPostProcessor,如果是实现了BeanDefinitionRegistryPostProcessor的类型,则调用对应的postProcessBeanDefinitionRegistry()方法进行相应处理并加入到registryPostProcessors中,否则加入到regularPostProcessors中。
  • 18-25行首先调用BeanFactory的getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)方法获取所有类型为BeanDefinitionRegistryPostProcessor的bean,然后放到List对象registryPostProcessorBeans中并且进行排序,排序之后循环调用每个bean的postProcessBeanDefinitionRegistry()方法。
    注:getBeansOfType()后续会有一个针对beanFactory的专门研究先不做详细分析,这里简单说一下排序,spring内部实现了一套排序方法,主要是一个Ordered接口,需要排序的对象实现这个接口的getOrder()方法,在进行排序的时候会对这个结果进行比较从而实现排序。另外假如某个对象实现的是PriorityOrdered接口则优先进行排序,同样情况则依旧比较getOrder()的结果。
  • 26-28行依次对3个List对象调用invokeBeanFactoryPostProcessors()方法,进行BeanFactoryPostProcessor的处理,顺序为registryPostProcessors、registryPostProcessorBeans、regularPostProcessors。invokeBeanFactoryPostProcessors()方法的代码很简单,就是for循环调用每个postProcessor对象的postProcessBeanFactory(beanFactory)方法。
  • 29行把所有bean中加载过来的BeanDefinitionRegistryPostProcessor类型的bean的名字加入到processedBeans中。
  • 回到上面最开始的判断,如果beanFactory类型没有实现BeanDefinitionRegistry接口,则直接调用invokeBeanFactoryPostProcessors()方法处理所有ApplicationContext已注册的BeanFactoryPostProcessor。

第2部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanFactoryPostProcessor. class , true , false );
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new  ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new  ArrayList<String>();
for  (String ppName : postProcessorNames) {
     if  (processedBeans.contains(ppName)) {
         // skip - already processed in first phase above
     }
     else  if  (isTypeMatch(ppName, PriorityOrdered. class )) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor. class ));
     }
     else  if  (isTypeMatch(ppName, Ordered. class )) {
         orderedPostProcessorNames.add(ppName);
     }
     else  {
         nonOrderedPostProcessorNames.add(ppName);
     }
}
OrderComparator.sort(priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
  
List<BeanFactoryPostProcessor> orderedPostProcessors = new  ArrayList<BeanFactoryPostProcessor>();
for  (String postProcessorName : orderedPostProcessorNames) {
     orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor. class ));
}
OrderComparator.sort(orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
  
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new  ArrayList<BeanFactoryPostProcessor>();
for  (String postProcessorName : nonOrderedPostProcessorNames) {
     nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor. class ));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
  • 第1、2行首先获取所有类型为BeanFactoryPostProcessor的bean的name集合放到变量postProcessorNames
  • 第3行建立一个ArrayList变量priorityOrderedPostProcessors用来存储需优先处理的postProcessor
  • 第4、5行分别建立两个ArrayList变量orderedPostProcessorNames、nonOrderedPostProcessorNames用来存储有排序的和无排序的postProcessor
  • 第6-19行循环上面获取到的所有postProcessor的name集合,按条件进行不同处理:
        如果name已经存在于processedBeans则代表是已经处理过了,跳过这一个;
        调用isTypeMatch()方法根据bean的name判断该bean是否实现了PriorityOrdered接口(上面我们说过排序中这个属于优先排序),如果是的话根据该name取出对应的bean对象加入到priorityOrderedPostProcessors集合中;
        调用isTypeMatch()方法根据bean的name判断该bean是否实现了Ordered接口(上面我们说过实现了这个接口就可以进行排序了),如果是的话把该name加入到orderedPostProcessorNames集合中;
        如果都上面条件都不成立,则加入到nonOrderedPostProcessorNames集合中;
    注:关于isTypeMatch()方法,说起来简单就是根据bean的name取出bean对象然后进行类型判断,但实际上这个方法并不简单,最终主逻辑代码在AbstractBeanFactory中,做个标记,以后单独抽出来分析一下。
  • 第20行对priorityOrderedPostProcessors进行排序
  • 第21行调用invokeBeanFactoryPostProcessors()方法对priorityOrderedPostProcessors中的所有postProcessor进行处理
  • 第23-28行通过getBean()方法取得所有orderedPostProcessorNames集合中postProcessor的bean对象,然后加入到一个新的集合变量orderedPostProcessors中,然后对这个集合排序,最后调用invokeBeanFactoryPostProcessors()方法处理
  • 后面的一部分是对无排序的nonOrderedPostProcessorNames进行处理,除了去掉排序步骤之外和上面的步骤一样,就不重复描述了

二、我们回到refresh()方法中,看下一行:registerBeanPostProcessors(beanFactory),这个方法主要就是对BeanPostProcessor的注册,依旧分为几部分来看:

第1部分:

?
1
2
3
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor. class , true , false );
int  beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor( new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
  • 第1行获取所有的BeanPostProcessor类型的bean的name数组
  • 第2行计算BeanPostProcessor的数量:banFactory中已注册的BeanPostProcessor的数量 + 1 + 上面获取到的所有bean中的BeanPostProcessor的数量。这里面的那个+1,是下一行的BeanPostProcessorChecker
  • 第3行注册一个BeanPostProcessorChecker到beanFactory中,这个BeanPostProcessor作用是当一个bean创建后没有被所有的BeanPostProcessor处理的时候打印一行info级别日志

 

第2部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new  ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new  ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new  ArrayList<String>();
for  (String ppName : postProcessorNames) {
     if  (isTypeMatch(ppName, PriorityOrdered. class )) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor. class );
         priorityOrderedPostProcessors.add(pp);
         if  (pp instanceof  MergedBeanDefinitionPostProcessor) {
             internalPostProcessors.add(pp);
         }
     }
     else  if  (isTypeMatch(ppName, Ordered. class )) {
         orderedPostProcessorNames.add(ppName);
     }
     else  {
         nonOrderedPostProcessorNames.add(ppName);
     }
}
  • 这部分代码与BeanFactoryPostProcessor的处理那部分类似,就是把所有的BeanPostProcessor进行区分放到不同集合里,优先的、排序的、无排序的。有个特殊的地方就是多了一个internalPostProcessors集合,用来存放优先级别中类型为MergedBeanDefinitionPostProcessor的BeanPostProcessor。它的主要作用是在spring运行时合并处理bean定义,例如注解中的bean定义,这部分也还没完全弄清楚,做个标记,回头专项分析。

第3部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
OrderComparator.sort(priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
  
List<BeanPostProcessor> orderedPostProcessors = new  ArrayList<BeanPostProcessor>();
for  (String ppName : orderedPostProcessorNames) {
     BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor. class );
     orderedPostProcessors.add(pp);
     if  (pp instanceof  MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
     }
}
OrderComparator.sort(orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
  
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for  (String ppName : nonOrderedPostProcessorNames) {
     BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor. class );
     nonOrderedPostProcessors.add(pp);
     if  (pp instanceof  MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
     }
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
  
OrderComparator.sort(internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
  
beanFactory.addBeanPostProcessor( new  ApplicationListenerDetector());
  • 第1-2行对priorityOrderedPostProcessors进行排序,并调用registerBeanPostProcessors()方法进行注册处理,这个方法内部代码比较简单,就是循环这个集合并调用beanFactory.addBeanPostProcessor(postProcessor)把每个BeanPostProcessor注册到beanFactory。
  • 第3-13行和之前也类似了,把所有orderedPostProcessorNames中的BeanPostProcessor取出来放到集合里,其中MergedBeanDefinitionPostProcessor类型的依旧加入到internalPostProcessors中。最后两行先排序,再调用registerBeanPostProcessors()方法进行注册处理
  • 第14-23行是对nonOrderedPostProcessorNames的处理,相比上面去掉了排序过程,其他依旧。
  • 紧接着的是对internalPostProcessors排序,注册处理。
  • 最后一行注册了一个BeanPostProcessor:ApplicationListenerDetector,这个是AbstractApplicationContext的内部类,实现了MergedBeanDefinitionPostProcessor接口,这个类只是暂时知道是在处理ApplicationListener相关的东西,具体作用还未知,留待分析。

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

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

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

?
1
2
3
4
5
6
7
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if  (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
     //第1部分
}
else  {
     //第2部分
}
  • 首先获取beanFactory对象,然后判断是否定义了名为messageSource的localbean,如果有则执行第1部分,否则执行第2部分,分别来看两部分代码 
    注:localbean实际上就是指查找的时候不会去parent查找这个bean,只从当前beanfactory去查找,很多地方有这个就不一一注明了

第1部分:

?
1
2
3
4
5
6
7
8
9
10
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部分:

?
1
2
3
4
5
6
7
8
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,使用默认

 

二、紧接着处理完messageSource的初始化后下一行代码:initApplicationEventMulticaster(),主要是对spring的事件监听器的管理器的初始话,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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(),这个方法的代码如下:

?
1
2
3
4
5
6
7
8
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的这几个功能模块做分别详细的分析。

refresh()方法中在上篇看完了MessageSource及时间监听器等初始话处理,这篇继续往下看。

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

一、finishBeanFactoryInitialization(beanFactory)这个方法将完成BeanFactory的初始化,主要做的事就是初始化除了之前处理过的特殊bean之外的所有单例bean,代码如下:

?
1
2
3
4
5
6
7
8
9
if  (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService. class )) {
     beanFactory.setConversionService(
             beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService. class ));
}
  
beanFactory.setTempClassLoader( null );
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();
  • 第1-5行判断如果定义了名为conversionService并且类型为ConversionService的bean,则把其设置为beanFactory的conversionService属性。这个主要是用来提供数据转化服务的
  • 销毁之前在prepareBeanFactory()中生成的临时ClassLoader
  • freezeConfiguration()的代码如下:
    ?
    1
    2
    3
    4
    this .configurationFrozen = true ;
    synchronized  ( this .beanDefinitionMap) {
         this .frozenBeanDefinitionNames = StringUtils.toStringArray( this .beanDefinitionNames);
    }
    这个方法就是代表bean定义等配置已经可以缓存了,不会再有其他地方对其做修改了
  • 最后一行就是对所有非延迟加载的单例bean进行初始化了我们来看下这个方法的代码:
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    if  ( this .logger.isInfoEnabled()) {
         this .logger.info( "Pre-instantiating singletons in "  + this );
    }
    synchronized  ( this .beanDefinitionMap) {
         for  (String beanName : this .beanDefinitionNames) {
             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
             if  (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                 if  (isFactoryBean(beanName)) {
                     final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                     boolean  isEagerInit;
                     if  (System.getSecurityManager() != null  && factory instanceof SmartFactoryBean) {
                         isEagerInit = AccessController.doPrivileged( new PrivilegedAction<Boolean>() {
                             public  Boolean run() {
                                 return  ((SmartFactoryBean) factory).isEagerInit();
                             }
                         }, getAccessControlContext());
                     }
                     else  {
                         isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit(); 
                     }
                     if  (isEagerInit) {
                         getBean(beanName);
                     }
                 }
                 else  {
                     getBean(beanName);
                 }
             }
         }
    }
    首先是一行info级别的日志,然后在对象beanDefinitionMap的同步下循环所有bean的name分别进行初始化
    首先获取bean定义信息对象bd,然后进行判断,这里只对非抽象bean(抽象bean是用于继承定义配置等信息的不可初始化)、单例、非延迟加载的bean进行处理
    判断如果是FactoryBean则进行下面的处理,如果不是直接调用getBean(beanName),这个方法调用会进行这个bean的初始化,关于这个方法还是放到BeanFactory的单独分析里面这里就不往里看了。
    对于FactoryBean的获取,要在beanname前加上一个&,然后会先判断是否是SmartFactoryBean并且渴望初始化(EagerInit),如果是才调用getBean(beanName),否则这个应该是在第一次调用工厂的getObject的时候才初始化
    注:对于这中间AccessController.doPrivileged的运用没有搞明白,留待以后分析,不知道为什么要在这里使用这个

二、最后的一个处理是finishRefresh()方法,代码如下:

?
1
2
3
initLifecycleProcessor();
getLifecycleProcessor().onRefresh();
publishEvent( new  ContextRefreshedEvent( this ));

1.先看initLifecycleProcessor()方法的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if  (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
     this .lifecycleProcessor =
             beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor. class );
     if  (logger.isDebugEnabled()) {
         logger.debug( "Using LifecycleProcessor ["  + this .lifecycleProcessor + "]" );
     }
}
else  {
     DefaultLifecycleProcessor defaultProcessor = new  DefaultLifecycleProcessor();
     defaultProcessor.setBeanFactory(beanFactory);
     this .lifecycleProcessor = defaultProcessor;
     beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this .lifecycleProcessor);
     if  (logger.isDebugEnabled()) {
         logger.debug( "Unable to locate LifecycleProcessor with name '"  +
                 LIFECYCLE_PROCESSOR_BEAN_NAME +
                 "': using default ["  + this .lifecycleProcessor + "]" );
     }
}

这个方法主要是用来初始化生命周期管理器LifecycleProcessor的

  • 如果用户定义了名为lifecycleProcessor类型为LifecycleProcessor的LocalBean,则赋值给当前ApplicationContext的lifecycleProcessor属性
  • 如果用户没有定义,则初始化默认的生命周期管理器DefaultLifecycleProcessor,注册单例bean,并赋值给lifecycleProcessor属性

2.initLifecycleProcessor()方法之后则是对生命周期管理器的触发,LifecycleProcessor有两个触发点onRefresh()和onClose(),当前正处于refresh所以调用其onRefresh()方法

3.调用publishEvent()方法发布ContextRefreshedEvent事件,publishEvent()的代码也很简单就不介绍了,就是调用当前上下文及parent的ApplicationEventMulticaster的multicastEvent()方法,这个放到分析事件处理模块时再去详细分析。

 

三、最后分析一下在整个try代码块中如果抛出异常的处理,可以看到分为了两个方法调用:

1.destroyBeans()代码很简单,就是调用BeanFactory的destroySingletons()方法销毁所有单例bean。还是暂不细看放到BeanFactory专项分析里去

2.cancelRefresh()这个方法代码看一下:

?
1
2
3
synchronized  ( this .activeMonitor) {
     this .active = false ;
}

就是在同步下设置状态值而已,但是有个小细节,这个方法在AbstractRefreshableApplicationContext和GenericApplicationContext两个子类中进行了重写,但是也很简单,就是增加了一个beanFactory.setSerializationId(null)然后依旧调用上面super中的方法进行修改状态

 

关于ApplicationContext的基本初始化的过车这就分析完了,中间碰到了很多问题,也还有很多地方需要详细研究,下面列举备忘一下,后面挨个分析:

  1. bean定义的加载
  2. bean的初始化
  3. BeanFactory的一些核心方法
  4. BeanFactory和ApplictionContext的关系以及各自的类继承框架
  5. 扩展点BeanFactoryPostProcessor及BeanPostProcessor
  6. 事件监听器ApplicationListener
  7. 信息管理器MessageSource
  8. 属性编辑器PropertyEditor
  9. 生命周期管理器LifecycleProcessor
  10. 还有几个小细节例如LoadTimeWeaver、MergedBeanDefinitionPostProcessor、AccessController.doPrivileged等
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值