什么是循环依赖?
先说一下什么是循环依赖,Spring在初始化A的时候需要注入B,而初始化B的时候需要注入A,在Spring启动后这2个Bean都要被初始化完成
Spring的循环依赖有4种场景
- 构造器的循环依赖(singleton,prototype)
- 属性的循环依赖(singleton,prototype)
「spring目前只支持singleton类型的属性循环依赖」
构造器的循环依赖
@Component
public class ConstructorA {
private ConstructorB constructorB;
@Autowired
public ConstructorA(ConstructorB constructorB) {
this.constructorB = constructorB;
}
}
@Component
public class ConstructorB {
private ConstructorA constructorA;
@Autowired
public ConstructorB(ConstructorA constructorA) {
this.constructorA = constructorA;
}
}
@Configuration
@ComponentScan("com.javashitang.dependency.constructor")
public class ConstructorConfig {
}
public class ConstructorMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ConstructorConfig.class);
System.out.println(context.getBean(ConstructorA.class));
System.out.println(context.getBean(ConstructorB.class));
}
}
运行ConstructorMain的main方法的时候会在第一行就报异常,说明Spring没办法初始化所有的Bean,即上面这种形式的循环依赖Spring无法解决。
「构造器的循环依赖,可以在构造函数中使用@Lazy注解延迟加载。在注入依赖时,先注入代理对象,当首次使用时再创建对象完成注入」
@Autowired
public ConstructorB(@Lazy ConstructorA constructorA) {
this.constructorA = constructorA;
}
因为我们主要关注属性的循环依赖,构造器的循环依赖就不做过多分析了
属性的循环依赖
先演示一下什么是属性的循环依赖
@Data
@Component
public class A {
@Autowired
private B b;
}
@Data
@Component
public class B {
@Autowired
private A a;
}
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.javashitang.dependency")
public class Config {
}
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(Config.class);
System.out.println(context.get