登录后台

页面导航

本文编写于 994 天前,最后修改于 984 天前,其中某些信息可能已经过时。

ApplicationContext的初始化过程

ClassPathXmlApplicationContext

ClassPathXmlApplication会接收一个applicationContext.xml(名称自定义)在类路径上描述spring bean的xml文件的构造方法。

  1. 初始化资源管理器PathMatchingResourcePatternResolver
  2. 解析xml路径上的占位符${...}
  3. 调用refresh()方法,该方法是高级容器的启动主要方法。

    1. 初始化容器上下文环境,主要内容为:

      1. 在上下环境中添加属性值用于替换占位符${...}
      2. 检测指定的环境变量是否已经配置。
    2. 初始化低级容器BeanFactory

      1. 创建容器 DefaultListableBeanFactory
      2. 定制容器,为容器设置参数:

        1. 是否允许BeanDefinition被覆盖;
        2. 是否允许循环依赖引用。
      3. 将xml文件的解析交给XmlBeanDefinitionReader
      4. 解析并注册,XmlBeanFactory的主要执行流程:

        1. 从classpath路径加载xml的Resource
        2. 检验并解析Resource资源得到Document
        3. 根据Document解析xml的各种属性标签;
        4. 将解析到的信息封装到BeanDefinition中;
        5. 注入到Spring容器beanDefinitionMap中。
    3. 为BeanFacotry做一些初步的功能扩展:

      1. 添加对SPEL表达式语言的支持;
      2. 注册属性编辑器;
      3. 添加执行器感知接口的后处理器;
      4. 添加ApplicationContext额外需要忽略的感知接口;
      5. 为指定接口注册对应的实现类
    4. BeanFactoryPostProcessor接口方法的执行;

      1. 处理参数传进来的beanFactoryPostProcessor
      2. beanFactory获取所有的BeanDefiitionRegistryPostProcessorPriorityOrdered接口和Ordered接口进行排序);
      3. beanFactory中获取所有BeanFactoryPostProcessorPriorityOrdered接口和Ordered接口进行排序)。
    5. 注册BeanPostProcessor:从beanFactory中获取所有BeanPostProcessorPriorityOrdered接口和Ordered接口进行排序)注册到Spring容器中;
    6. 初始化消息源MessageSource
    7. 初始化事件广播器ApplicationEventMulticaster
    8. 注册监听器ApplicationListener
    9. 初始化非延迟加载的单例;
    10. 开启Spring的生命周期。

AnnotationConfigApplicationContext

AnnotationConfigApplicationContext会接收一个扫描的包路径(名称自定义)的构造方法。

  1. 委托ClassPathBeanDefinitionScanner,将扫描的包路径转换为文件路径格式,例如:classpath*:com/test/**/*.class,扫描出路径下的所有类并转换为资源Resource数组;
  2. 通过注解过滤器,过滤出标注了@Component的类并封装为注解类型的AnnotatedBeanDefinition接口的实现类AnnotatedGenericBeanDefinition
  3. 筛选出符合实例化bean条件的BeanDefinition,放入Set<BeanDefinition> candidates
  4. 循环处理每个BeanDefinition

    1. 解析@Scope注解的信息,并设置到BeanDefinition中;
    2. 设置BeanDefinition默认的一些属性值;
    3. 解析其它注解信息:@Lazy@Primary@DependsOn@Role@Description
  5. BeanDefinition封装成BeanDefinitionHolder,注入到Spring容器beanDefinitionMap中;
  6. 调用refresh()方法,该方法是高级容器的启动主要方法。

    1. 初始化容器上下文环境;
    2. 初始化低级容器ConfigurableListableBeanFactory
    3. 为BeanFacotry做一些初步的功能扩展:

      1. 添加对SPEL表达式语言的支持;
      2. 注册属性编辑器;
      3. 添加执行器感知接口的后处理器;
      4. 添加ApplicationContext额外需要忽略的感知接口;
      5. 为指定接口注册对应的实现类
    4. BeanFactoryPostProcessor接口方法的执行(使用ConfigurationClassPostProcessor后置处理器处理@Configuration@Bean注解,流程在下一节);

      1. 处理参数传进来的beanFactoryPostProcessor
      2. beanFactory获取所有的BeanDefiitionRegistryPostProcessorPriorityOrdered接口和Ordered接口进行排序);
      3. beanFactory中获取所有BeanFactoryPostProcessorPriorityOrdered接口和Ordered接口进行排序)。
    5. 注册BeanPostProcessor:从beanFactory中获取所有BeanPostProcessorPriorityOrdered接口和Ordered接口进行排序)注册到Spring容器中;
    6. 初始化消息源MessageSource
    7. 初始化事件广播器ApplicationEventMulticaster
    8. 注册监听器ApplicationListener
    9. 初始化非延迟加载的单例;
    10. 开启Spring的生命周期。

ConfigurationClassPostProcessor

ConfigurationClassPostProcessor实现了接口BeanDefinitionRegistryPostProcessor,而BeanDefinitionRegistryPostProcessor接口继承自BeanFactoryPostProcessor,所以有两个关键的方法:BeanFactoryPostProcessor接口的postProcessBeanFactory方法和BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法。

postProcessBeanDefinitionRegistry方法

  1. 获取Spring容器中注册的所有BeanDefinition进行遍历;
  2. 如果BeanDefinition配置了工厂方法,该BeanDefinition不做处理,实现了工厂方法意味着在工厂方法中定义了实例化对象逻辑,不符合成为注解配置类BeanDefinition的条件;
  3. 获取BeanDefinition上的注解元数据metadata,将存在注解@Configuration且属性proxyBeanMethods的值为trueBeanDefinition添加到集合configCandidates中;
  4. 对集合configCandidates根据注解@Order进行排序;
  5. 初始化注解配置类的解析器ConfigurationClassParser
  6. 解析注解配置类中的其它注解,例如:@PropertySources@ComponentScansImportResource等;
  7. 将解析后的集合对象Set<ConfigurationClass>
  8. 遍历集合Set<ConfigurationClass>,对ConfigurationClass中每个添加了@Bean的方法创建一个BeanDefition,在填充一些默认属性后再注册到Spring容器中;
  9. 同时对这些@Bean对应的BeanDefinition进行重复检查(重复执行步骤3),以处理嵌套注解配置。

BeanFactoryPostProcessor方法

  1. 获取Spring容器中注册的所有BeanDefinition进行遍历;
  2. 找到存在属性CONFIGURATION_CLASS_ATTRIBUTE且为AbstractBeanDefinition实例的BeanDefinition
  3. 初始化增强器ConfigurationClassEnhancer
  4. 遍历步骤2找到的BeanDefinition,获取BeanDefinition的类名,使用增强器ConfigurationClassEnhancerconfigClass进行增强,得到增强后的enchancedClass
  5. enchancedClass设置回调接口BeanFactoryAwareMethodInterceptor,为字段$$beanFactory注入当前Spring容器对象;
  6. enchancedClass设置回调接口BeanMethodInterceptor,获取@Bean对应的bean的名称beanName:
  7. 使用&+beanName获取FactoryBean

    • 未获取到FactoryBean

      • 如果当前方法刚好是@Bean指定的工厂方法,通过@Bean对应的bean的cglib动态代理来执行;
      • 如果当前方法不是@Bean指定的工厂方法,从Spring容器获取bean的实例来执行(也就是@Bean方法中自定义创建的bean实例);
    • 获取到FactoryBean

      1. 类型或getObject方法存在final关键字修饰,如果@Bean标注的方法返回值是接口类型的,就会通过jdk动态代理方式来生成FactoryBean的动态代理,否则,就会直接返回FactoryBean
      2. 如果FactoryBean的类或方法getObject都没有被关键字final修饰,此时会对FactoryBean使用cglib动态代理的方式未FactoryBean生成一个动态代理;
      3. 不管是jdk动态代理还是cglib动态代理,如果当前bean实例调用的方法名称是getObject,此时会根据bean的名称,从Spring容器中获取bean的实例。