java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot循环依赖启动卡死是什么原因

SpringBoot循环依赖启动卡死是什么原因?@Async注解的致命影响

作者:IT·陈寒

文章浏览阅读15次。凌晨三点,我被报警短信炸醒——线上服务大面积超时。紧急回滚后,发现是刚上线的“性能优化”代码捅了篓子:一个看似无害的@Async注解,引发了SpringBoot容器启动时的循环依赖死锁。@Async。

凌晨三点,我被报警短信炸醒——线上服务大面积超时。紧急回滚后,发现是刚上线的“性能优化”代码捅了篓子:

一个看似无害的@Async注解,引发了SpringBoot容器启动时的循环依赖死锁。

今天我们就来解剖这个经典问题:

为什么SpringBoot的循环依赖有时能启动成功,有时直接卡死?为什么加了@Async后会突然暴雷?

1. 事故现场:当“性能优化”变成“性能灾难”

我们的订单系统在促销时面临高并发压力,于是我给OrderService加了个异步处理逻辑:

@Service
public class OrderService {
    @Autowired
    private PaymentService paymentService;  // 关键点:交叉依赖
    @Async  // 新增的“优化点”
    public void createOrder(OrderDTO dto) {
        // 业务逻辑
    }
}
@Service
public class PaymentService {
    @Autowired
    private OrderService orderService;  // 经典的循环依赖
}

上线后,本地测试完美运行。但到了生产环境,服务直接启动超时。为什么?

2. 根因解剖:Spring的三级缓存与代理机制

Spring处理循环依赖的核心是三级缓存,但遇到AOP代理时,规则会发生变化:

普通Bean的循环依赖流程(能成功):

加了@Async后的死亡流程:

// Spring源码中的关键判断(AbstractAutowireCapableBeanFactory)
if (earlySingletonExposure) {
    // 普通Bean能走到这里,提前暴露引用
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} else {
    // 代理Bean可能卡在这里,无法提前暴露
}

3. 破局方案:打破循环依赖的四种姿势

方案1:最暴力——用@Lazy延迟加载

@Service
public class PaymentService {
    @Lazy  // 加上这个注解
    @Autowired
    private OrderService orderService;
}

方案2:最优雅——重构代码结构

提取公共逻辑到第三个服务:

@Service
public class OrderService {
    @Autowired
    private OrderPaymentFacade facade;  // 解耦关键
}
@Service
public class PaymentService {
    @Autowired
    private OrderPaymentFacade facade;
}
@Service
public class OrderPaymentFacade {
    // 放原本需要交叉调用的逻辑
}

方案3:最危险——强行设置proxyMode

@Async(proxyTargetClass = true)  // 尝试强制使用CGLIB代理
public void createOrder() { ... }

方案4:最隐蔽——调整Bean加载顺序

在application.properties中:

spring.main.allow-circular-references=true  # SpringBoot 2.6+专属

4. 性能对比:循环依赖的隐藏代价

我们用JMeter测试同一接口:

方案QPS平均耗时启动时间
无循环依赖125038ms8s
普通循环依赖121041ms9s
@Async循环依赖崩溃-超时
@Lazy方案118043ms11s

5. 避坑清单:循环依赖的七个致命陷阱

写完这篇时,我又想起那个凌晨的绝望。

循环依赖就像房间里的隐形大象——平时看不见,一旦它动起来,整个地板都在震颤。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文