点击查看【processon】

概述

Spring容器初始化过程,会伴随着Bean的初始化,下文将以AnnotationConfigApplicationContext类为例,从源码开始讲解Spring容器的初始化和Bean的初始化过程。

专业术语

简称 名称
ACAC AnnotationConfigApplicationContext 基于注解配置类的spring容器上下文
pp PostProcessor 后置处理器。以BeanFactoryPostProcessor为例,在BF初始化完成,实例化其他bean之前会调用所有对BF的后置处理器。

源码

从ACAC构造看spring容器加载过程

  1. // demo启动类的main方法中 new一个AnnotationConfigApplicationContext
  2. public static void main(String[] args) {
  3. // 传入一个配置类
  4. AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(DefConfig.class);
  5. DemoBan bean = annotationConfigApplicationContext.getBean(DemoBan.class);
  6. bean.sayHello();
  7. }
  8. // 自定义的配置类 将决定spring扫描哪些包下面的bean
  9. @ComponentScan("com.demo.springweb")
  10. public static class DefConfig {
  11. @Bean
  12. MyPostProcessor myPostProcessor(){
  13. return new MyPostProcessor();
  14. }
  15. }
  1. public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
  2. this();
  3. register(annotatedClasses);
  4. refresh();
  5. }

可以看到AnnotationConfigApplicationContext(以上简称ACAC)类中构造方法主要包含注册刷新两个方法。

  • 注册: 读取应用程序提供的bean配置信息,并在容器中生成一张bean配置注册表;
  • 刷新:

注册

配置类装配成BeanDefinition
调用org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>, java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>…) 方法,将配置类装配成BeanDefinition后存放到 beanDefinitionMap

刷新

  1. prepareRefresh(); 准备上下文 ,初始化ACAC的父类AbstractApplicationContext中的一些属性
  2. obtainFreshBeanFactory(); 获取并刷新BeanFactory
  3. prepareBeanFactory(bf);

初始化BeanFactory

  • 设置ignoreDepencyInterfaces, 忽略给定接口的自动装配功能
  • 添加系统的PostProcessors
  • 注册systemProperties,systemEnvrionment在内的系统bean到beanFactory

systemProperies里存放java运行环境,jdk版本、编码等
systemEnvrionment存放maven_home, mainclass等

  1. postProcessBeanFactory()

    ACAC类中为空实现,允许其他AbstractApplicationContext的子类对BeanFactory做后置处理

  2. invokeBeanFactoryPostProcessors()

调用所有的BeanFactoryPostProcessors,包括spring容器内置的和bean扫描到用户自定义的。

  • 调用系统pp

ACAC中系统的pp主要是:ConfigrationClassPostProcessor,其核心方法processConfigBeanDefinitions主要是做:

  • 拿到应用程序定义(如代码一中的DefConfig)的config配置类对应的BeanDefinition
  • 调用ConfigurationClassParser类的parse方法,对应用程序定义配置类解析
    • parse方法中调用ComponentScanAnnotationParser.parse方法,对程序定义配置类中的定义的包路径扫描
      • 调用ClassPathBeanDefinitionScanner.scan方法扫描对应包路径下所有的Bean对应的BeanDefinition,并注册到beanDefinitionMap。 (这里并不会直接实例化)
        • 调用应用程序定义的pp
  • 从BeanFactory获取所有应用定义的pp(代码块一中的MyPostProcessor),没有实例化则先实例化
  • 调用pp的postProcessBeanDefinitionRegistry方法
  1. registerBeanPostProcessors() 注册bpp,仅注册不会调用

BeanPostProcessor接口的核心方法是postProcessBeforeInitialization,postProcessAfterInitialization分别将在bean实例化前和实例化后被调用。

  • 找到并实例化所有的BeanPostProcessors
  • 添加到DefalutListableBeanFactory的BeanPostProcessors中去,供bean实例化前后调用

Spring容器内置的BeanPostProcessor有:

  1. - ApplicationContextAwareProcessor
  2. - CommonAnnotationBeanPostProcessor
  3. - AutowriedAnnotationBeanPostProcessor
  4. - RequireAnnotaionBeanPostProcessor
  5. - ApplicationListenerDetecotr
  1. initMessageSource()
  1. initApplicationEventMulticaster()


  1. onRefresh();

空实现

  1. registerListeners()

注册应用监听器

  1. finishBeanFactoryInitialization(beanFactory);

这一步主要是实例化所有单列bean.

  • beanFactory.setTempClassLoader(null);// Stop using the temporary ClassLoader for type matching.
  • beanFactory.freezeConfiguration()

冻结全部bean定义,给被注册的bean定义发信号告诉它们今后不再被修改和进一步后续处理。它允许factory去积极缓存bean定义元数据。

  • beanFactory.preInstantiateSingletons()

实例化所有单例

  1. 根据在beanDefinitionNames注册的beanName,找到所有的beanDefinition
  2. 实例化所有单例bean到singletonObjects. 调用DefaultListableBeanFactory中的doGetBean方法, 有则返回,没有则反射实例化注册到singletonObjects的map中并返回

实例化bean前后还有其他复杂操作,下文再讲
c. 对实现了SmartInitializingSingleton接口的bean,调用其afterSingletonsInstantiated()方法。

  1. finishRefresh()

其他

beanFactory.preInstantiateSingletons() Bean的实例化