spring 循环依赖以及解决方式

一、循环依赖定义

简单来说就是在你的某个 AService 中(已经注入到容器),注入了 BService ,但是在BService 中, 也同时注入了 AService,两个 service 形成了循环互相依赖。

在一般的场景中更多的是说
A 依赖 B, B 依赖 C, 然而 C 反过来依赖 A 这样也构成了循环

当循环形成会导致无法判断先注入那一个导致系统抛出错误

The dependencies of some of the beans in the application context form a cycle

即 某些类在系统上下文中形成了一个循环

二、解决方式

2.1 spring boot 配置修改

当使用spring boot 时且版本升级到较高时系统启动时若检查到循环依赖会直接错误导致无法启动。
2.3 系列版本不会检查出改问题,但是若升级到2.6及以上 系列则会启动失败

一个方法是修改spring boot 的启动配置

spring:
	main:
		allow-circular-references: true

此配置为允许循环依赖的存在,但不是很推荐

2.2 代码结构重设计

一般来说形成循环依赖都是因为代码结构设计不合理,导致互相依赖,实际上应将服务方法等单独提出作为公共类或底层服务取消循环的形成,但也有少部分情况下一定需要这样的写法,那么下面也有其他方式可以解决。

实际代码设计时如果代价或者时间允许情况下可以考虑代码结构的再设计者通过 applicationContext 来提取公共类,作为单独属性来使用服务从而解决循环依赖。

2.3 通过 set 方法注入

即类加载属性时 我们不对要使用的类直接使用 @Autowired 注入,而是当作一般的类注入,通过set 方式来完成需要时再注入,也就是延迟了注入的时机从而解决同时加载时的循环依赖错误

@Service
public class XxxxxxService {

    private XxxxAService xxxxAservice;

    @Autowired
    public void setCatalogRepository(XxxxAService  xxxxAservice) {
        this.xxxxAservice = xxxxAservice;
    }
}

如果上面那样还是没有解决那么可以加个 @Lazy 如下(自己摸索的方法 可能不适用)

@Service
public class XxxxxxService {

    private XxxxAService xxxxAservice;

    @Autowired
    public void setCatalogRepository(@Lazy XxxxAService  xxxxAservice) {
        this.xxxxAservice = xxxxAservice;
    }
}

2.4 @Lazy 注解 构造方法中注入

实际上 @Lazy 注解 与上面使用set 方法解决的原理基本一致,使用 @Lazy 后属性在启动时将不会立即去注入,而是实际使用时再去 注入该属性。

实际使用可以如下

@Service
public class XxService {

    private CcAService ccAservice;

    @Autowired
    public XxService(@Lazy CcAService ccAservice) {
        this.ccAservice = ccAservice;
    }
}

或者 直接在被循环注入的类上再加注解 @Lazy (所在包 import org.springframework.context.annotation.Lazy;)
具体可以参考之前遇到的问题链接看是否是一样的错误
Bean with name ‘XX‘ has been injected into other beans [XX,XX] in its raw version… 错误分析及解决

2.5 通过 @PostConstruct

写法比较麻烦,大致示例如下:
原理与上面一致 基本也是在错开两个类的注入顺序,从而完成解锁

@Service
public class XxService {

	@Autowired
    private CcAService ccAservice;

    @PostConstruct
    public void init() {
        ccAservice.setXxService(this);
    }

	public CcAService getCcAService() {
        return ccAservice;
    }

}

在另一个类中

@Service
public class CcAService {

	@Autowired
    private XxService xxService ;

	public void setXxService(XxService xxService) {
        this.xxService = xxService;
    }

}

2.6 替换方法

检查代码需要的service一类 是否可以通过其他类同等替代,替代后也可以达成解锁的效果

2.7 spring 三级缓存

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值