spring解决循环依赖的方案

文章讲述了在Spring框架中遇到ServiceA和服务B的循环依赖问题,分析了Spring解决循环依赖的原理,并提出了四种解决方案:属性或setter注入,启用允许循环引用配置,使用@Lazy进行懒加载,以及通过@PostConstruct和InitializingBean接口控制初始化顺序。最后强调最佳实践是避免编写存在循环依赖的代码。
摘要由CSDN通过智能技术生成

问题描述

当ServiceA和ServiceB相互依赖的时候,就会出现循环依赖的问题,循环依赖的代码可能如下:

@Component
public class A {
    // A中注入了B
    @Autowired
    private B b;
}

@Component
public class B {
    // B中也注入了A
    @Autowired
    private A a;
}

在启动服务的时候会报错。
在这里插入图片描述

问题分析

解决循环依赖的思路有两种,一种是在相互依赖的bean中新增中间状态,在一方依赖另一方的时候先给其一个中间状态的引用,待依赖双方创建完成后,再进行初始化,这个是spring解决循环依赖的思路。

另一种是在一个依赖的bean创建成功之后,再创建另一个bean,或者再手动触发另一个bean的依赖注入。这个是手动解决依赖注入的思路。

解决方案

方案一:

使用属性注入或setter注入方式。这种方式spring框架解决了注入依赖的问题。

@Component
public class Service1 {
    @Autowired
    private Service2 service2;
}
@Component
public class Service1 {
    private Service2 service2;

    @Autowired
    public Service1(Service2 service2) {
        this.service2 = service2;
    }
}

在springboot中使用以上方法解决注入依赖,还是会报依赖注入的错误,需要在配置文件application.properties中添加配置项:spring.main.allow-circular-references=true

方案二:

使用@Lazy。使用Bean的懒加载方式,在bean需要的时候才初始化它,这样规避了启动context的时候对有依赖关系的bean进行初始化从而报错的问题。

@Component
public class Service1 {
    private Service2 service2;

    @Autowired
    public void setService2(@Lazy Service2 service2) {
        this.service2 = service2;
    }
}

方案三:

使用@PostConstruct注解,在一个bean初始化后再初始化另一个。

@Component
public class CircularDependencyA {
 
    @Autowired
    private CircularDependencyB circB;
 
    @PostConstruct
    public void init() {
        circB.setCircA(this);
    }
 
    public CircularDependencyB getCircB() {
        return circB;
    }
}

方案四:

实现InitializingBean。该接口可以实现在bean初始化前后再进行操作的功能,通过实现ApplicationContextAware接口。

@Component
public class CircularDependencyA implements ApplicationContextAware, InitializingBean {
 
    private CircularDependencyB circB;
 
    private ApplicationContext context;
 
    public CircularDependencyB getCircB() {
        return circB;
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        circB = context.getBean(CircularDependencyB.class);
    }
 
    @Override
    public void setApplicationContext(final ApplicationContext ctx) throws BeansException {
        context = ctx;
    }
} 

问题总结

以上的解决循环依赖的方案都是存在循序依赖后才介入解决,其实最好的思路应该是不要再代码中存在循序依赖的逻辑,这样的逻辑本身可能就不合理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yangnk42

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值