zoukankan      html  css  js  c++  java
  • spring Bean创建过程详解

    复习一下spring实现IOC的源码流程

    准备工作:

    ​ 强烈建议大家从git上拉取spring源码来学习Spring源码。因为里面相较于IDEA生成的会有注释,里面有的方法会有注释看起来会省力一点。

    ​ 以下都是用5.0.2版本来做阐述。

    bean创建的流程图

    写在前面:建议大家一定要自己用实例跑一遍,做好记录。如果只是看看会非常抽象。此流程图作为梗概,便于加强记忆和理解,新手或无基础的有个印象即可。等跟随本文走通一遍,在回过头看这个图,或许会有收获

    springbean lifecycle.jpg

    源码走一遍

    bean的定义

    1. 这是我的bean目录结构,只是做一个例子

    image.png

    1. 获取核心容器对象,bean最后都会放在此容器对象中

          *   ApplicationContext的三个实现类
          *   ClassPathXmlApplicationContext  它可以加载类路径下的配置文件,要求必须在类路径下
          *   FileSystemXmlApplicationContext  可以加载任意路径下的配置文件,必须有访问权限
          *   AnnotationConfigApplicationContext 用于读取注解创建容器的
          
          这里我用ClassPathXmlApplicationContext来做演示
          
         public class MyTest {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
          }
      }
      

    快速开始

    1. 建议用IDEA的debug模式来观察Spring的IOC过程

      image.png

      • 进入到此类的构造方法中image.png

        • 查看setConfigLocations,就是将配置文件加载到configLocations里去image.png
      • 向下执行,查看refresh()image.png

        • this.prepareRefresh(): 此方法是准备工作,大家感兴趣可以点进去看一下,可以看到里面是获取时间,获取环境信息的一些设置。

        • this.obtainFreshBeanFactory(): 这一步是创建beanFactory,并且读取Bean的信息,源码注释中还有写到

          // Tell the subclass to refresh the internal bean factory.会告诉子类去刷新内部bean工厂
          
          • this.refreshBeanFactory:

            	 * This implementation performs an actual refresh of this context's underlying
            	 * bean factory, shutting down the previous bean factory (if any) and
            	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
            	 
            	 这个实现类的方法会刷新容器中的beanFactory,关闭之前存在的并且初始化新的beanFactory
            

            image.png

        • 利用this.createBeanFactory() 创建了一个beanFactory,类型为DefaultListableBeanFactory

        • 这个类接着往下走:this.loadBeanDefinitions(beanFactory);

          	 * Load bean definitions into the given bean factory, typically through
          	 * delegating to one or more bean definition readers.
          	 
          	 这个方法会将beandefinitionsReader读取到的bean definitions放入bean工厂,我们以上提出的三种
          	 注入方式都会走到这里,将bean信息丢进去
          
      • 返回上述 refresh()

        • this.prepareBeanFactory(beanFactory); 设置和忽略一些对象值

        • this.postProcessBeanFactory(beanFactory); 空方法可自定义扩展

        • this.invokeBeanFactoryPostProcessors(beanFactory);

          	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
          	 * respecting explicit order if given.
          	 * <p>Must be called before singleton instantiation.
          	 
          	 实例化所有beanFactory组件
          
        • registerBeanPostProcessors(beanFactory);

          Instantiate and register all BeanPostProcessor beans,  //先注册再调用
          
        • initApplicationEventMulticaster(); 观察者模式监听器, 监听组件的相关状态,并决定相关调用方法。

        • finishBeanFactoryInitialization(beanFactory); 重要!!

          	 * Finish the initialization of this context's bean factory,
          	 * initializing all remaining singleton beans.
          	 
          	 完成了容器bean factory的初始化,并且初始化其他的bean单例对象
          
      • beanFactory.preInstantiateSingletons(); 实例化方法

        • 此方法最后this.getBean(beanName)

          • 继续image.png

          • Return an instance, which may be shared or independent, of the specified bean.
            
            注释已经很清楚了,此方法会返回一个实例,就是我们的bean对象
            

            image.png

        • 进入到createBean方法中image.png

        • 继续进入![image-20200714221630608](/Users/hjj/Library/Application Support/typora-user-images/image-20200714221630608.png)

        • 继续进入

          image.png

          image.png

          Instantiate the given bean using its default constructor.
          
          这个方法注释说明了实例化对象是用构造器完成的
          
          • 继续看他如何构造的image.png

          • image.png

          • image.png

            ca 就是Constructor,从这里我们基本可以看出容器内,bean对象的实例化
            是利用反射的基本原理,获取类构造器,然后newInstance来实现的
            
        • 以上就是bean对象实例化的基本过程,下面是实例化完成后的初始化过程

        • 回到这里,实例化完成后

          image.png
          image.png

          注释说明了在populateBean完成bean的初始化

        • 继续image.png

          会看到在此方法里会调用前置和后置处理器来初始化Bean
          
      • 以上就完成了bean的实例化过程,文章开头的那个图刚开始有点懵,但是一旦跑完一遍bean的实例化过程,再次结合图,就清晰了很多。本文只是简单的跟随debug顺序,完整的走了一遍bean实例化的过程,还有特殊情况并没有讨论,后期会重新用新文章再来拓展。

    如有不足还请指正。

  • 相关阅读:
    Spring 中众多的的Initializer
    Spring Factories
    spring 的各种context
    @import和@Bean的区别,以及ImportSelector和ImportBeanDefinitionRegistrar两个接口的简单实用
    Spring 配置的方式
    记一次JAVA FULL GC问题处理【3】
    关于String, StringBuilder,StringBuffer 的一些测试数据
    记一次JAVA FULL GC问题处理【2】
    ThreadLocal 结构
    记一次JAVA FULL GC问题处理【1】
  • 原文地址:https://www.cnblogs.com/jimmyhe/p/13976202.html
Copyright © 2011-2022 走看看