设为首页 加入收藏

TOP

Spring中的循环依赖解决详解(一)
2019-09-03 03:40:17 】 浏览:62
Tags:Spring 循环 依赖 解决 详解

前言


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


一、先说说Spring解决的循环依赖是什么


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


@Service
public class Student {
? ? @Autowired
? ? private Teacher teacher;


? ? public Student (Teacher teacher) {
? ? ? ? System.out.println("Student init1:" + teacher);
? ? }


? ? public void learn () {
? ? ? ? System.out.println("Student learn");
? ? }
}


?


@Service
public class Teacher {
? ? @Autowired
? ? private Student student;


? ? public Teacher (Student student) {
? ? ? ? System.out.println("Teacher init1:" + student);


? ? }


? ? public void teach () {
? ? ? ? System.out.println("teach:");
? ? ? ? student.learn();
? ? }
}


?


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


Spring解决的循环依赖就是指属性的循环依赖,如下所示:


@Service
public class Teacher {
? ? @Autowired
? ? private Student student;


? ? public Teacher () {
? ? ? ? System.out.println("Teacher init1:" + student);


? ? }


? ? public void teach () {
? ? ? ? System.out.println("teach:");
? ? ? ? student.learn();
? ? }
? ?
}


?


@Service
public class Student {
? ? @Autowired
? ? private Teacher teacher;


? ? public Student () {
? ? ? ? System.out.println("Student init:" + teacher);
? ? }


? ? public void learn () {
? ? ? ? System.out.println("Student learn");
? ? }
}


测试扫描类:


1 @ComponentScan(value = "myPackage")
2 public class ScanConfig {
3? ?
4 }


测试启动类:


public class SpringTest {


? ? public static void main(String[] args) {
? ? ? ? AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanConfig.class);
? ? ? ? applicationContext.getBean(Teacher.class).teach();


? ? }
}


测试类执行结果:


1 Student init:null
2 Teacher init:null
3 teach:
4 Student learn


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


二、循环依赖与属性注入


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


1 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
2? ? ? ? // 其他代码
3
4? ? ? ? // Instantiate all remaining (non-lazy-init) singletons.
5? ? ? ? beanFactory.preInstantiateSingletons();
6? ? }


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


2、DefaultListableBeanFactory的preInstantiateSingletons方法


public void preInstantiateSingletons() throws BeansException {
? ? ? ?
? ? ? ? List beanNames = new ArrayList<>(this.beanDefinitionNames);


 
Spring中的循环依赖解决详解(一) https://www.cppentry.com/bencandy.php?fid=54&id=249488

首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python类中的魔法方法之 __slots__ 下一篇Spring源码解读之BeanFactoryPost..

kafka-
kafka ? Partit
解决android studio
Kafka史上最详细原理
Error while fetchin
【Kafka】安装与快速
? ? &
flume读取日志数据写
Authentication plug
Flume 自定义source
flume ? 三大核
ICC副本>>>
愚公移山 ?
Hbase架构 ? Hb
5 hbase-shell + &
Hbase ? MapRed
MetaException(messa
Exception in thread
HIVE metastore Dupl
-->