DefaultListableBeanFactory 相关机制探索

DefaultListableBeanFactory 相关机制探索

本文的分析以 DefaultListableBeanFactory 为对象。

spring-beans依赖的版本为 5.0.9.RELEASE

类图

DefaultListableBeanFactory 相关机制探索_第1张图片

关键属性
  • DefaultSingletonBeanRegistry

    • private final Map singletonObjects: 存放完全实例化并且属性赋值完成的 Bean ,可以直接使用(一级缓存);
    • private final Map earlySingletonObjects: 存放早期的单例的 bean 的引用,尚未配置属性(二级缓存);
    • private final Map> singletonFactories: 存放单例的工厂 (三级缓存);
    • private final Set singletonsCurrentlyInCreation: 当前正在被创建的 bean 的缓存,创建前(createBean)放入,创建后移除;
    • private boolean singletonsCurrentlyInDestruction: 当前是否在销毁 singleton 对象,如果是的话,此时创建单例对象会报异常;
    • private final Map disposableBeans: 需要进行销毁操作的 bean
  • AbstractBeanFactory:

    • private final Set alreadyCreated: 记录那些被创建了至少一次的 bean 名称;
    • private final ThreadLocal prototypesCurrentlyInCreation: 当前正在被创建的原型 bean,泛型中可以是字符串类型,存 bean 名称,也可以是 Set 类型存多个原型的 bean 的名称;
      关键方法
      • DefaultListableBeanFactory#preInstantiateSingletons:实例化所有非抽象的,非延迟加载的单例 Bean
        • 循环所有的 bean 名称列表,对每个名称,用 getBean(String) 方法获取 bean
        • 循环所有的单例 bean ,如果是 SmartInitializingSingleton 类型就执行回调方法
      • AbstractBeanFactory#doGetBean: 获取 bean, 如果 bean 不存在还会进行创建
      • DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean): 从三级缓存中获取单例 bean
      • AbstractAutowireCapableBeanFactory#createBeanInstance: 创建bean实例
      • AbstractAutowireCapableBeanFactory#populateBean: 为 bean 注入属性
      • DefaultListableBeanFactory#destroySingletons: 销毁所有的单例 bean
      BeanFactory doGetBean过程
      • doGetBean 流程概览:

        DefaultListableBeanFactory 相关机制探索_第2张图片

      • getSingleton(String beanName, ObjectFactory singletonFactory) 流程概览:

        DefaultListableBeanFactory 相关机制探索_第3张图片

      • polulateBean 方法执行流程:

        DefaultListableBeanFactory 相关机制探索_第4张图片

      BeanFactory#destroySingletons 销毁过程
      • 设置 singletonsCurrentlyInDestruction 这个属性为 true
      • 遍历这个属性 disposableBeans,调用其中的每个 bean 的销毁方法;
      • 销毁每个 bean 之前,先销毁其依赖,如果有循环依赖的情况,不影响(比如 A 依赖 B,B 又依赖 A,A先开始进入销毁方法,结果是 B销毁,A再销毁);
      属性注入循环依赖

      两个相互依赖的类:

      @Setter
      @Getter
      public class Man {
          private String name;
          private Woman wife;
      
          @Override
          public String toString() {
              return "Man{" + "name='" + name + '\'' + ", wife=" + wife.getName() + '}';
          }
      }
      
      @Setter
      @Getter
      public class Woman {
          private String name;
          private Man husband;
      
          @Override
          public String toString() {
              return "Woman{" + "name='" + name + '\'' + ", husband=" + husband.getName() + '}';
          }
      }
      

      手动注册 BeanDefinition 到容器中:

      public class CycleDependencyByPropertyDemo {
          @Test
          public void autowireDemo(){
              DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
              // 通过代码注册bean
              bindBeansByCode(beanFactory);
              // 获取bean
              Man man = (Man) beanFactory.getBean("man");
              System.out.println(man);
          }
      
          private static void bindBeansByCode(BeanDefinitionRegistry beanDefinitionRegistry) {
              // 注册man
              GenericBeanDefinition manDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                      .genericBeanDefinition(Man.class)
                      .addPropertyReference("wife", "woman")
                      .addPropertyValue("name", "Jack")
                      .getBeanDefinition();
      
              // 注册woman
              GenericBeanDefinition womanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                      .genericBeanDefinition(Woman.class)
                      .addPropertyReference("husband", "man")
                      .addPropertyValue("name", "Alice")
                      .getBeanDefinition();
      
              beanDefinitionRegistry.registerBeanDefinition("man", manDefinition);
              beanDefinitionRegistry.registerBeanDefinition("woman", womanDefinition);
          }
      }
      

      执行结果:

      Man{name='Jack', wife=Alice}
      
      Process finished with exit code 0
      

      结论:通过属性注入是没有循环依赖发生的。

      解决这类循环依赖的关键在于:

      • 将刚刚实例化的 beanObjectFactory 的方式提供在 private final Map> singletonFactories (第三级缓存)属性中;
      • getSingleton(String beanName, boolean allowEarlyReference) 中从第三级缓存中和第二级缓存中取还未创建完全的 bean
      带有DependsOn关系的属性注入

      如果基于上述的例子加入 dependsOn 关系,就会导致异常,改造后代码如下

      private static void bindBeansByCode(BeanDefinitionRegistry beanDefinitionRegistry) {
              // 注册man
              GenericBeanDefinition manDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                      .genericBeanDefinition(Man.class)
                      .addPropertyReference("wife", "woman")
                      .addPropertyValue("name", "Jack")
      +               .addDependsOn("woman")
                      .getBeanDefinition();
      
              // 注册woman
              GenericBeanDefinition womanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                      .genericBeanDefinition(Woman.class)
                      .addPropertyReference("husband", "man")
                      .addPropertyValue("name", "Alice")
      +               .addDependsOn("man")
                      .getBeanDefinition();
      
              beanDefinitionRegistry.registerBeanDefinition("man", manDefinition);
              beanDefinitionRegistry.registerBeanDefinition("woman", womanDefinition);
          }
      

      输出如下:

      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'woman': Circular depends-on relationship between 'woman' and 'man'
      	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:304)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
      	at com.zmf.spring.bean.cycle.CycleDependencyByPropertyWithDependsOnDemo.autowireDemo(CycleDependencyByPropertyWithDependsOnDemo.java:21)
      

      结论:带有DependsOn关系就不能解决循环依赖

      构造器注入循环依赖

      两个相互依赖的类如下:

      @Setter
      @Getter
      public class ConMan {
          private String name;
          private ConWoman wife;
      
          public ConMan(String name, ConWoman wife) {
              this.name = name;
              this.wife = wife;
          }
      
          @Override
          public String toString() {
              return "ConMan{" + "name='" + name + '\'' + ", wife=" + wife.getName() + '}';
          }
      }
      
      @Setter
      @Getter
      public class ConWoman {
          private String name;
          private ConMan husband;
      
          public ConWoman(String name, ConMan husband) {
              this.name = name;
              this.husband = husband;
          }
      
          @Override
          public String toString() {
              return "ConWoman{" + "name='" + name + '\'' + ", husband=" + husband.getName() + '}';
          }
      }
      

      测试类 CycleDependencyByConstructorDemo 以构造器相互注入的形式实例化 bean,代码如下:

      public class CycleDependencyByConstructorDemo {
          @Test
          public void constructDemo(){
              DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
              // 通过代码注册bean
              bindBeansByCode(beanFactory);
              // 获取bean
              ConMan man = (ConMan) beanFactory.getBean("man");
              System.out.println(man);
          }
      
          private static void bindBeansByCode(BeanDefinitionRegistry beanDefinitionRegistry) {
              // 注册man
              GenericBeanDefinition manDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                      .genericBeanDefinition(ConMan.class)
                      .addPropertyValue("name", "Jack")
                      .addConstructorArgValue("Jack")
                      .addConstructorArgReference("woman")
                      .getBeanDefinition();
      
              // 注册woman
              GenericBeanDefinition womanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                      .genericBeanDefinition(ConWoman.class)
                      .addConstructorArgValue("Alice")
                      .addConstructorArgReference("man")
                      .getBeanDefinition();
      
              beanDefinitionRegistry.registerBeanDefinition("man", manDefinition);
              beanDefinitionRegistry.registerBeanDefinition("woman", womanDefinition);
          }
      }
      

      执行结果如下:

      Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'man': Requested bean is currently in creation: Is there an unresolvable circular reference?
      

      结论:构造器注入的循环依赖不能自动解决

      Bean 生命周期

      DefaultListableBeanFactory 相关机制探索_第5张图片

      参考资料

      手动注册BeanDefinition

      spring中的三级缓存

      你可能感兴趣的:(源码,spring)