spring的循环依赖问题与解决方案

前言

最近的一次面试被问到了这个,完全不知道,没去刷面试题。经过探究发现这一学拉出一堆玩意

  1. bean声明周期
  2. 循环依赖的定义
  3. spring的代理
  4. spring三级缓存

循环依赖是什么?

其实很简单、使用注解将类给spring管理后,a类使用@Autowired依赖了b类,b类又依赖了a类,那么仔细一想,spring初始化注册bean ababababab无线循环下去了,这时候spring会报错:

1
Requested bean is currently in creation: Is there an unresolvable circular reference?

但是并不是说循环依赖都会报错,我一直没有报过这个错,拿代码实现一下

1
2
3
4
5
6
7
8
9
@Component
public class ComponentA {
@Autowired
private ComponentB componentB;

public void A(){
componentB.B();
}
}
1
2
3
4
5
6
7
8
9
10
11
@Component
//@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ComponentB {
@Autowired
private ComponentA componentA;
public void B(){

System.out.println(this.getClass().getName() + " -----> say()");
}
}

1
2
3
4
5
6
@Configuration
@ComponentScan(basePackages = { "com.zykj.zhixing.auth.core.test" })
public class TestConfig {

}

1
2
3
4
5
6
7
8
9
10
11
12
13
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyTest {
@Autowired
private ComponentA componentA;
@Test
public void givenCircularDependency_whenConstructorInjection_thenItFails() {
componentA.A();
// Empty test; we just want the context to load

}
}

这样一运行是不会报错的,经过查询资料,主要是有两种情况 单例的循环依赖和构造参数的注入是会报错,借图一i用

image-20220515164237301

上面这种是依靠与spring的三级缓存自行解决了

image-20220515173339580

bean的生命周期

三级缓存也代表了对象创建或是bean的生命周期

  1. 实列化对象 new (在一级缓存查找是否有完整bean,没有则 new一个半成品bean放入二级缓存 )
  2. 属性注入
  3. 初始化 (初始化时将对象存入三级缓存,初始化完成存入一级缓存,将二级三级缓存的bean删除)
  4. 销毁bean (从一级缓存中删除)

创建、初始化、调用、销毁

spring的代理

代理分动态代理和静态代理,区别就是动态代理无需再去手动创建类交由spring去管理,而是用代码运行时进行创建的。

动态代理有俩种,一种是jdk的方式、一种是spring的CGLIB代理,默认为jdk的代理方式,当需要代理的类没有实现代理接口的时候,Spring会切换为使用CGLIB代理。

参考:

https://blog.csdn.net/mywaya2333/article/details/122399020

三级缓存

这篇说的很好

https://baijiahao.baidu.com/s?id=1711380208642133437&wfr=spider&for=pc

image-20220528222734397