简介
说明
本文用实例介绍如何解决Spring的循环依赖问题。
相关网址
Spring--循环依赖导致启动失败_IT利刃出鞘的博客-博客_springboot 配置循环依赖
公共代码
package com.example.controller;
import com.example.tmp.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
private A a;
@GetMapping("/test1")
public String test1() {
return a.getTest();
}
}
方案1. Feild注入单例(@AutoWired)
代码
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A {
@Autowired
private B b;
private String name = "Tony";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTest() {
return b.getAge().toString() + name;
}
}
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class B {
@Autowired
private A a;
private Integer age = 20;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
测试
启动不报错。
postman访问:http://localhost:8080/test1
后端结果:不报错
postman结果: 20Tony
方案2. 构造器注入+@Lazy
延迟加载:在注入依赖时,先注入代理对象,当首次使用时再创建对象完成注入。
代码
package com.example.tmp;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class A {
private B b;
public A(@Lazy B b) {
this.b = b;
}
private String name = "Tony";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTest() {
return b.getAge().toString() + name;
}
}
package com.example.tmp;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class B {
private A a;
public B(@Lazy A a) {
this.a = a;
}
private Integer age = 20;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
测试
启动不报错。
postman访问:http://localhost:8080/test1
后端结果:不报错
postman结果: 20Tony
方案3. Setter/Field注入单例
代码
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A {
private B b;
private String name = "Tony";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTest() {
return b.getAge().toString() + name;
}
public B getB() {
return b;
}
@Autowired
public void setB(B b) {
this.b = b;
}
}
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class B {
private A a;
private Integer age = 20;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public A getA() {
return a;
}
@Autowired
public void setA(A a) {
this.a = a;
}
}
测试
启动不报错。
postman访问:http://localhost:8080/test1
后端结果:不报错
postman结果: 20Tony
方案4. @PostConstruct
代码
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class A {
@Autowired
private B b;
@PostConstruct
public void init() {
b.setA(this);
}
private String name = "Tony";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTest() {
return b.getAge().toString() + name;
}
}
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class B {
@Autowired
private A a;
private Integer age = 20;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
测试
启动不报错。
postman访问:http://localhost:8080/test1
后端结果:不报错
postman结果: 20Tony
方案5. 实现ApplicationContextAware与InitializingBean
代码
package com.example.tmp;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class A implements ApplicationContextAware, InitializingBean {
private B b;
private ApplicationContext context;
private String name = "Tony";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTest() {
return b.getAge().toString() + name;
}
@Override
public void afterPropertiesSet() throws Exception {
this.b = context.getBean(B.class);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
package com.example.tmp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class B {
@Autowired
private A a;
private Integer age = 20;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
测试
启动不报错。
postman访问:http://localhost:8080/test1
后端结果:不报错
postman结果: 20Tony