• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Spring中循环依赖的解决方法详析

java 搞代码 4年前 (2022-01-09) 19次浏览 已收录 0个评论

前言

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

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

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

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

@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;<strong style="color:transparent">本文来源gaodai#ma#com搞@@代~&码网^</strong>

  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");
  }
}

测试扫描类:

 @ComponentScan(value = "myPackage")
 public class ScanConfig {
 
 }

测试启动类:

public class SpringTest {

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

  }
}

测试类执行结果:

 Student init:null
 Teacher init:null
 teach:
 Student learn

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

二、循环依赖与属性注入

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

 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
 // 其他代码
 
 // Instantiate all remaining (non-lazy-init) singletons.
 beanFactory.preInstantiateSingletons();
 }

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Spring中循环依赖的解决方法详析

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址