这篇文章主要介绍了简单了解春天循环依赖解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
<强>前言强>
说起春天中循环依赖的解决办法,相信很多园友们都或多或少的知道一些,但当真的要详细说明的时候,可能又没法一下将它讲清楚。本文就试着尽自己所能,对此做出一个较详细的解读,另需注意一点,下文中会出现类的实例化跟类的初始化两个短语,为怕园友迷惑,事先声明一下,本文的实例化是指刚执行完构造器将一个对象新出来,但还未填充属性值的状态,而初始化是指完成了属性的依赖注入。
<强>一、先说说春天解决的循环依赖是什么强>
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); } } }//其他无关代码 } 简单了解春天循环依赖解决过程