简单了解春天循环依赖解决过程

  

这篇文章主要介绍了简单了解春天循环依赖解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  

<强>前言

  

说起春天中循环依赖的解决办法,相信很多园友们都或多或少的知道一些,但当真的要详细说明的时候,可能又没法一下将它讲清楚。本文就试着尽自己所能,对此做出一个较详细的解读,另需注意一点,下文中会出现类的实例化跟类的初始化两个短语,为怕园友迷惑,事先声明一下,本文的实例化是指刚执行完构造器将一个对象新出来,但还未填充属性值的状态,而初始化是指完成了属性的依赖注入。

  

<强>一、先说说春天解决的循环依赖是什么

  

Java中的循环依赖分两种,一种是构造器的循环依赖,另一种是属性的循环依赖。

  

构造器的循环依赖就是在构造器中有属性循环依赖,如下所示的两个类就属于构造器循环依赖:

        @ service   公开课学生{   @ autowired   私人教师的老师;      公开学生(老师老师){   system . out。println(“学生init1:“+老师);   }      公共空间学习(){   system . out。println(“学生学习”);   }   }            @ service   公开课的老师{   @ autowired   私人学生学生;      公共老师(学生学生){   system . out。println(“老师init1:“+学生);      }      公共空间教(){   System.out.println(“教:”);   student.learn ();   }   }      

这种循环依赖没有什么解决办法,因为JVM虚拟机在对类进行实例化的时候,需先实例化构造器的参数,而由于循环引用这个参数无法提前实例化,故只能抛出错误。

  

<强>春解决的循环依赖就是指属性的循环依赖强,如下所示:

        @ service   公开课的老师{   @ autowired   私人学生学生;      公共老师(){   system . out。println(“老师init1:“+学生);      }      公共空间教(){   System.out.println(“教:”);   student.learn ();   }      }            @ service   公开课学生{   @ autowired   私人教师的老师;      公共的学生(){   system . out。println(“学生初始化:“+老师);   }      公共空间学习(){   system . out。println(“学生学习”);   }   }      

测试扫描类:

        @ComponentScan (value=" https://www.yisu.com/zixun/myPackage ")   公开课ScanConfig {      }      

测试启动类:

        公开课SpringTest {      公共静态void main (String [] args) {   所applicationContext=new所(ScanConfig.class);   applicationContext.getBean (Teacher.class) .teach ();      }   }      

测试类执行结果:

        学生init:零   老师init:零   教:   学生学习      

可以看的到,在构造器执行的时候未完成属性的注入,而在调用方法的时候已经完成了注入。下面就一起看看春天内部是在何时完成的属性注入,又是如何解决的循环依赖。

  

<强>二,循环依赖与属性注入

  

1,对于非懒加载的类,是在刷新方法中的finishBeanFactoryInitialization (beanFactory)方法完成的包扫描以及豆的初始化、下面就一起追踪下去。

        保护无效finishBeanFactoryInitialization (ConfigurableListableBeanFactory beanFactory) {//其他代码//实例化所有剩余(non-lazy-init)单件。   beanFactory.preInstantiateSingletons ();   }      

可以看到调用了beanFactory的一个方法,此处的beanFactory就是指我们最常见的那个DefaultListableBeanFactory、下面看它里面的这个方法。

  

2, DefaultListableBeanFactory的preInstantiateSingletons方法

        公共空间preInstantiateSingletons()抛出BeansException {      ListbeanNames=new ArrayList<祝辞(this.beanDefinitionNames);//触发初始化所有非延迟的单例bean……   (字符串beanName: beanNames) {   RootBeanDefinition bd=getMergedLocalBeanDefinition (beanName);   如果(! bd.isAbstract (),,bd.isSingleton (),,! bd.isLazyInit()){//判断为非抽象类,是单例,非懒加载才给初始化   如果(isFactoryBean (beanName)) {//无关代码(针对FactoryBean的处理)   }   其他{//重要!普通豆就是在这里初始化的   getBean (beanName);   }   }   }//其他无关代码   }

简单了解春天循环依赖解决过程