深入剖析循环依赖产生与解决的原理前戏
深入剖析循环依赖产生与解决的原理前戏
方式一:通过构造函数方式进行注入
创建两个类:
package com.coding.spring.practies;
public class TestCircularBeanA {
private TestCircularBeanB testCircularBeanB;
public TestCircularBeanA(TestCircularBeanB testCircularBeanB) {
this.testCircularBeanB = testCircularBeanB;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanB.say());
}
}
package com.coding.spring.practies;
public class TestCircularBeanB {
private TestCircularBeanA testCircularBeanA;
public TestCircularBeanB(TestCircularBeanA testCircularBeanA) {
this.testCircularBeanA = testCircularBeanA;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanA.say());
}
}
创建xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--通过构造函数注入-->
<bean id="testCircularBeanA" class="com.coding.spring.practies.TestCircularBeanA">
<constructor-arg ref="testCircularBeanB"></constructor-arg>
</bean>
<bean id="testCircularBeanB" class="com.coding.spring.practies.TestCircularBeanB">
<constructor-arg ref="testCircularBeanA"></constructor-arg>
</bean>
</beans>
编写测试方法:
@Test
public void obtainBeanByPureAnnotation4(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-practies.xml");
TestCircularBeanA circularBeanA = context.getBean(TestCircularBeanA.class);
TestCircularBeanB circularBeanB = context.getBean(TestCircularBeanB.class);
circularBeanA.print();
circularBeanB.print();
}
运行结果分析:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testCircularBeanA' defined in class path resource [spring-practies.xml]: Cannot resolve reference to bean 'testCircularBeanB' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testCircularBeanB' defined in class path resource [spring-practies.xml]: Cannot resolve reference to bean 'testCircularBeanA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testCircularBeanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
从报错信息上面我们能够看出来,是否有一个没有解决的循环引用依赖。
方式二:使用set方法注入
创建两个类:
package com.coding.spring.practies;
public class TestCircularBeanA {
private TestCircularBeanB testCircularBeanB;
public TestCircularBeanB getTestCircularBeanB() {
return testCircularBeanB;
}
// 通过set方法注入
public void setTestCircularBeanB(TestCircularBeanB testCircularBeanB) {
this.testCircularBeanB = testCircularBeanB;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanB.say());
}
}
package com.coding.spring.practies;
public class TestCircularBeanB {
private TestCircularBeanA testCircularBeanA;
public TestCircularBeanA getTestCircularBeanA() {
return testCircularBeanA;
}
// 通过set方法注入
public void setTestCircularBeanA(TestCircularBeanA testCircularBeanA) {
this.testCircularBeanA = testCircularBeanA;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanA.say());
}
}
创建spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--通过set方法注入-->
<bean id="testCircularBeanA" class="com.coding.spring.practies.TestCircularBeanA">
<property name="testCircularBeanB" ref="testCircularBeanB"></property>
</bean>
<bean id="testCircularBeanB" class="com.coding.spring.practies.TestCircularBeanB">
<property name="testCircularBeanA" ref="testCircularBeanA"></property>
</bean>
</beans>
编写测试类:
@Test
public void obtainBeanByPureAnnotation4(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-practies.xml");
TestCircularBeanA circularBeanA = context.getBean(TestCircularBeanA.class);
TestCircularBeanB circularBeanB = context.getBean(TestCircularBeanB.class);
circularBeanA.print();
circularBeanB.print();
}
运行结果分析:
class com.coding.spring.practies.TestCircularBeanA---->class com.coding.spring.practies.TestCircularBeanB-->I am say()
class com.coding.spring.practies.TestCircularBeanB---->class com.coding.spring.practies.TestCircularBeanA-->I am say()
由此可以通过set注入的方式能够解决循环依赖的问题。
方式三:通过自动扫描的方式注入
创建两个类:
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanA {
private TestCircularBeanB testCircularBeanB;
public TestCircularBeanB getTestCircularBeanB() {
return testCircularBeanB;
}
// 通过set方法注入加上@Autowired注解
@Autowired
public void setTestCircularBeanB(TestCircularBeanB testCircularBeanB) {
this.testCircularBeanB = testCircularBeanB;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanB.say());
}
}
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanB {
private TestCircularBeanA testCircularBeanA;
public TestCircularBeanA getTestCircularBeanA() {
return testCircularBeanA;
}
// 通过set方法注入加上@Autowired注解
@Autowired
public void setTestCircularBeanA(TestCircularBeanA testCircularBeanA) {
this.testCircularBeanA = testCircularBeanA;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanA.say());
}
}
创建测试类:
@Test
public void obtainBeanByPureAnnotation4(){
ApplicationContext context = new AnnotationConfigApplicationContext("com.coding.spring.practies");
TestCircularBeanA circularBeanA = context.getBean(TestCircularBeanA.class);
TestCircularBeanB circularBeanB = context.getBean(TestCircularBeanB.class);
circularBeanA.print();
circularBeanB.print();
}
运行结果分析:
class com.coding.spring.practies.TestCircularBeanA---->class com.coding.spring.practies.TestCircularBeanB-->I am say()
class com.coding.spring.practies.TestCircularBeanB---->class com.coding.spring.practies.TestCircularBeanA-->I am say()
由此可以,使用set方式结合扫描注解能够解决循环依赖的问题
方式四:通过构造方法加注解的方式注入
创建两个类:
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanA {
private TestCircularBeanB testCircularBeanB;
// 通过构造方法注入加上@Autowired注解
@Autowired
public TestCircularBeanA(TestCircularBeanB testCircularBeanB) {
this.testCircularBeanB = testCircularBeanB;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanB.say());
}
}
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanB {
private TestCircularBeanA testCircularBeanA;
// 通过构造方法注入加上@Autowired注解
@Autowired
public TestCircularBeanB(TestCircularBeanA testCircularBeanA) {
this.testCircularBeanA = testCircularBeanA;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanA.say());
}
}
编写测试类:
@Test
public void obtainBeanByPureAnnotation4(){
ApplicationContext context = new AnnotationConfigApplicationContext("com.coding.spring.practies");
TestCircularBeanA circularBeanA = context.getBean(TestCircularBeanA.class);
TestCircularBeanB circularBeanB = context.getBean(TestCircularBeanB.class);
circularBeanA.print();
circularBeanB.print();
}
运行结果分析:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testCircularBeanA' defined in file [D:\ideaProject\spring-framework\coding-example\build\classes\java\main\com\coding\spring\practies\TestCircularBeanA.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testCircularBeanB' defined in file [D:\ideaProject\spring-framework\coding-example\build\classes\java\main\com\coding\spring\practies\TestCircularBeanB.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testCircularBeanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
是否有一个未解决的循环依赖
由此可见,这种方式会产生循环依赖。
方式五:使用@Lazy懒加载的方式进行解决
创建两个类:
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanA {
private TestCircularBeanB testCircularBeanB;
// 通过构造方法注入加上@Lazy注解
@Autowired
public TestCircularBeanA(TestCircularBeanB testCircularBeanB) {
this.testCircularBeanB = testCircularBeanB;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanB.say());
}
}
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanB {
private TestCircularBeanA testCircularBeanA;
// 通过构造方法注入加上@Lazy注解
@Autowired
public TestCircularBeanB(@Lazy TestCircularBeanA testCircularBeanA) {
this.testCircularBeanA = testCircularBeanA;
}
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanA.say());
}
}
编写测试类:
@Test
public void obtainBeanByPureAnnotation4(){
ApplicationContext context = new AnnotationConfigApplicationContext("com.coding.spring.practies");
TestCircularBeanA circularBeanA = context.getBean(TestCircularBeanA.class);
TestCircularBeanB circularBeanB = context.getBean(TestCircularBeanB.class);
circularBeanA.print();
circularBeanB.print();
}
运行结果分析:
class com.coding.spring.practies.TestCircularBeanA---->class com.coding.spring.practies.TestCircularBeanB-->I am say()
class com.coding.spring.practies.TestCircularBeanB---->class com.coding.spring.practies.TestCircularBeanA-->I am say()
由此可见,这种方式能够解决循环依赖的。其中,@Lazy注解只要加到其中一个类上就可以了。
方式六:字段属性上加@Autowired注解
创建两个类:
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanA {
@Autowired
private TestCircularBeanB testCircularBeanB;
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanB.say());
}
}
package com.coding.spring.practies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TestCircularBeanB {
@Autowired
private TestCircularBeanA testCircularBeanA;
public String say(){
return this.getClass() + "-->I am say()";
}
public void print(){
System.out.println(this.getClass() + "---->" + testCircularBeanA.say());
}
}
编写测试类:
@Test
public void obtainBeanByPureAnnotation4(){
ApplicationContext context = new AnnotationConfigApplicationContext("com.coding.spring.practies");
TestCircularBeanA circularBeanA = context.getBean(TestCircularBeanA.class);
TestCircularBeanB circularBeanB = context.getBean(TestCircularBeanB.class);
circularBeanA.print();
circularBeanB.print();
}
运行结果分析:
class com.coding.spring.practies.TestCircularBeanA---->class com.coding.spring.practies.TestCircularBeanB-->I am say()
class com.coding.spring.practies.TestCircularBeanB---->class com.coding.spring.practies.TestCircularBeanA-->I am say()
由此可见,这种方式是能够解决循环依赖的。
其中
@Autowired
private TestCircularBeanA testCircularBeanA;
等同于:
@Autowired
public void setTestCircularBeanA(TestCircularBeanA testCircularBeanA) {
this.testCircularBeanA = testCircularBeanA;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
2021-07-28 多媒体技术基础概念-计算题 小k和大K 小b和大B
2021-07-28 toPlainString()
2020-07-28 insert into values 大数据量报错An I/O error occurred while sending to the backend.