yeskery

ApplicationContext的初始化过程

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获取所有的BeanDefiitionRegistryPostProcessor(PriorityOrdered接口和Ordered接口进行排序);
      3. 从beanFactory中获取所有BeanFactoryPostProcessor(PriorityOrdered接口和Ordered接口进行排序)。
    5. 注册BeanPostProcessor:从beanFactory中获取所有BeanPostProcessor(PriorityOrdered接口和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获取所有的BeanDefiitionRegistryPostProcessor(PriorityOrdered接口和Ordered接口进行排序);
      3. 从beanFactory中获取所有BeanFactoryPostProcessor(PriorityOrdered接口和Ordered接口进行排序)。
    5. 注册BeanPostProcessor:从beanFactory中获取所有BeanPostProcessor(PriorityOrdered接口和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的值为true的BeanDefinition添加到集合configCandidates中;
  4. 对集合configCandidates根据注解@Order进行排序;
  5. 初始化注解配置类的解析器ConfigurationClassParser;
  6. 解析注解配置类中的其它注解,例如:@PropertySources、@ComponentScans、ImportResource等;
  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的类名,使用增强器ConfigurationClassEnhancer对configClass进行增强,得到增强后的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的实例。

评论

Post comment Click Refresh verification code

Tip

The feature is not yet available