Spring IOC加载过程

一、Spring 源码解析主要步骤概述

  1、解析配置,创建 Bean 容器,加载并注册 Bean名 和 Bean定义 到 Bean容器;

  2、注册和执行 BeanFactory容器后处理器 (BeanFactoryPostProcessor ) 的实例;

  3、注册 “Bean后处理器”( BeanPostProcessor ),即 注册 BeanPostProcessor 的实现类;

  4、创建事件传播器对象;

  5、预先实例化单实例

 

二、源码

      // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
      // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
      // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 
      // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
      // 这块待会会展开说
      prepareBeanFactory(beanFactory);

      // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
      // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
      postProcessBeanFactory(beanFactory);
      // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
      invokeBeanFactoryPostProcessors(beanFactory);
 
      // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
      // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
      // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
      registerBeanPostProcessors(beanFactory);
 
      //(分析这里略过) 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
      initMessageSource();
 
      // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
      initApplicationEventMulticaster();
 
      // 从方法名就可以知道,典型的模板方法(钩子方法),
      // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
      onRefresh();
 
      // (分析略过, 不是重点)注册事件监听器,监听器需要实现 ApplicationListener 接口
      registerListeners();
 
      // 重点,重点,重点
      // 初始化所有的 singleton beans
      //(lazy-init 的除外)
      finishBeanFactoryInitialization(beanFactory);
 
      // 最后,广播事件,ApplicationContext 初始化完成
      finishRefresh();

 

三、Spring IOC加载源码主要步骤详细

一、解析配置,创建 Bean 容器,加载并注册 Bean名 和 Bean定义 到 Bean容器

加载:

  加载配置文件,可以是xml 或者 Java 配置类, Spring 提供了统一的抽象接口 BeanDefinitationReader 去处理这些配置信息。

  对于不同的载体的配置有不同的实现类, 比如 xml 就有 XmlBeanDefinitionReader 的实现类。

解析:

  解析 Bean 标签,和对应 Bean 的 class 名, id, 别名信息,properties属性,还有是否懒加载,是否原型类型初始化init-method配置等 方法名。

注册:

  容器通过 map 的形式 保存以 Bean 为 key, 和 Bean定义(上述的解析内容)的键值对 ,完成注册。

 

二、  注册和执行 BeanFactory容器后处理器 (BeanFactoryPostProcessor ) 的实例

  设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean, 或者 修改,移除,现有的 BeanDefinition 信息。

  提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,

BeanFactoryPostProcessor 怎么提供给框架

  容器启动的时候,它会检查 BeanDefinition 信息, 会将“ 容器后处理器” 接口实现类的配置 抽象出来,然后反射创建实例,并且执行接口方法。

 

三、注册 “Bean后处理器”( BeanPostProcessor ),即 注册 BeanPostProcessor 的实现类

  注意:和 BeanFactory容器后处理器( BeanFactoryPostProcessor) 的区别,

      "BeanFactory容器后处理器" 是在实例化单例之前就执行的,然后 “Bean后处理器” 是实例化,每个实例的过程中穿插执行的。

      “Bean后处理器” 有两个接口方法,调用点是 实例 init-method 初始化方法执行的前后。“Bean后处理器” 接口还有一些子接口,子接口还提供了实例化前后增强的方法入口等。

      “Bean后处理器” 是Spring 容器和兴拓展点技术,Spring本身提供了很多“Bean后处理器”接口的实现类。

  这里主要说 Bean后处理器 的作用。

  可以通过“Bean后处理器” 处理链中的某一个后处理器实例,实现接口 ApplicationContextAware 接口,取到 ApplicationContext 实例

  解析自动装配的注解 @Autowired @Value, 还有 AOP 面向切面编程,也是依靠 BeanPostProcessor 去完成

 

四、创建事件传播器对象

  在Spring容器 生命周期内,在关键阶段接受相应事件并传播

  比如说,某个 BeanDefinition 信息处理完成之后, 也就是创建出来对应的单实例后,保存到缓存中, 会发出“事件” 到 “事件传播器” 里。

  事件传播器 可以注册很多监听者( listener ), 传播器把事件广播出去以后, listener 就收到事件了。

监听者怎么提供给事件传播器  

  java 类实现 Spring 的 监听者接口,并且在 xml 配置对应的 bean。

  Spring 容器启动过程中,会根据类型去获取这些 BeanDefinition 信息,并且实例化后注册到事件传播器内

 

五、预先实例化单例

创建和初始化MergedBeanDefinition

  创建一个新的 beanDefinition 对象 叫 MergedBeanDefinition, 然后将 parent beanDefinition 信息拷贝到 MergedBeanDeifition 中。

  然后将当前的 BeanDefinition 覆盖到 MergedBeanDefinition里。这样就获取到包含 paren 信息和包含当前 BeanDefinition 信息的MergedBeanDefinition。

实例化 depends - on 指定的 bean  

  再往下看就是当前bean 有没有 配置 depends - on 依赖。

  如果配置的话,就先实例化 depends - on 指定的 bean。

 根据 bean 定义的 class 信息 还有构造方法信息,通过反射完成实例化对象

  再往下,就是根据 bean 定义的 class 信息 还有构造方法信息,去找合适的构造方法。最后会拿到合适的构造方法,并通过反射完成实例化对象。

  到这步就创建出 beanDefinition 对应的对象。 

  这个对象还有很多逻辑要处理,比如 依赖注入,还有 “init-method” 配置的初始化方法的调用等等这些逻辑。

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

【1】https://www.cnblogs.com/Jomini/p/13820335.html

【2】https://www.cnblogs.com/Jomini/p/13753711.html

 

 

 

  

posted @ 2020-10-17 14:07  抽象Java  阅读(899)  评论(0编辑  收藏  举报