java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring无法解决循环依赖

Spring无法解决循环依赖的五种场景分析

作者:雾缘枯

本文详细分析Spring框架中五类循环依赖问题(构造器注入、原型作用域、@Async、配置类、BeanPostProcessor),提出应急方案如@Lazy、重构设计,并强调通过单一职责、依赖倒置等设计原则避免循环依赖,需要的朋友可以参考下

一、构造器注入引发的循环依赖

1. 问题复现

@Component
public class ServiceA {
    private final ServiceB serviceB;
    
    @Autowired
    public ServiceA(ServiceB serviceB) { // 构造器注入
        this.serviceB = serviceB;
    }
}
 
@Component
public class ServiceB {
    private final ServiceA serviceA;
    
    @Autowired
    public ServiceB(ServiceA serviceA) { // 构造器注入
        this.serviceA = serviceA;
    }
}

报错信息:Requested bean is currently in creation: Is there an unresolvable circular reference?

2. 原理分析

3. 解决方案

@Autowired
  public ServiceA(@Lazy ServiceB serviceB) { 
      this.serviceB = serviceB;
  }

二、原型(Prototype)作用域的循环依赖

1. 问题复现

@Scope("prototype")
@Component
public class PrototypeA {
    @Autowired private PrototypeB b;
}
 
@Scope("prototype")
@Component
public class PrototypeB {
    @Autowired private PrototypeA a;
}

2. 原理分析

3. 解决方案

三、@Async 注解导致的代理冲突

1. 问题复现

@Service
public class AsyncServiceA {
    @Autowired private AsyncServiceB serviceB;
    
    @Async
    public void asyncMethod() { /* ... */ }
}
 
@Service
public class AsyncServiceB {
    @Autowired private AsyncServiceA serviceA;
}

2. 原理分析

BeanCreationException: Error creating bean with name 'asyncServiceA': 
Bean with name 'asyncServiceA' has been injected into other beans [...] in their raw version as part of a circular reference.

3. 解决方案

@Async
public interface AsyncService {
    void asyncMethod();
}
 
@Service
public class AsyncServiceImpl implements AsyncService { /* ... */ }
@Autowired @Lazy private AsyncServiceA serviceA;

四、Configuration 类之间的循环依赖

1. 问题复现

@Configuration
public class ConfigA {
    @Autowired private ConfigB configB;
}
 
@Configuration
public class ConfigB {
    @Autowired private ConfigA configA;
}

2. 原理分析

3. 解决方案

@Configuration
@DependsOn("configB")
public class ConfigA { /* ... */ }

五、自定义 BeanPostProcessor 引发的冲突

1. 问题复现

@Component
public class CustomProcessor implements BeanPostProcessor {
    @Autowired private ServiceX x; // 依赖其他Bean
}

2. 原理分析

3. 解决方案

private ObjectProvider<ServiceX> xProvider;
  
  public Object postProcessBeforeInitialization(Object bean, String beanName) {
      ServiceX x = xProvider.getIfAvailable();
      // ...
  }

六、终极解决方案工具箱 

问题类型应急方案根治方案
构造器循环依赖@Lazy 注解改为 Setter 注入
原型Bean循环依赖重构作用域引入中间类抽象依赖
AOP代理冲突接口代理模式调整切面作用顺序
配置类循环依赖@DependsOn 指定顺序合并配置类
BeanPostProcessor依赖ObjectProvider 延迟获取分离处理器与业务逻辑

结语:跳出循环依赖的思维陷阱

Spring 的循环依赖处理机制体现了框架设计的高度智慧,但作为开发者,最优雅的解决方案往往不是技术手段,而是架构设计。通过以下原则可从根本上避免循环依赖:

  1. 单一职责原则:拆分臃肿的 Bean

  2. 依赖倒置原则:面向接口编程

  3. 层次化设计:Controller -> Service -> Repository 的严格分层

以上就是Spring无法解决循环依赖的五种场景分析的详细内容,更多关于Spring无法解决循环依赖的资料请关注脚本之家其它相关文章!

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