highlight: arduino-light
    
     解决循环依赖\&bean实例化过程
    
     什么是循环引用?
    
下面的代码中,两个类相互引用,就是循环依赖。
     
      java @Component public class OrderService {     @Autowired    UserService userService;        public OrderService(){        System.out.println("OrderService——>"+userService);   } }  @Component public class UserService {     @Autowired    OrderService orderService;     public UserService(){        System.out.println("UserService->" + orderService);   } }  /*** 但是如果分别指定类的构造方法为以下形式 就无法解决。 因为通过构造方法传入要求必须传入一个实例化后的对象。 OrderService(UserService   userService ); UserService(OrderService orderService); ***/
     
     “`java public class SpringTest {
     
    
public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new 
                                AnnotationConfigApplicationContext();
    context.register(Config.class);
    context.refresh();
}} “`
bean的实例化是在refresh()——>finishBeanFactoryInitialization(beanFactory);方法里完成的。
该方法只能实例化单例的类。
这两个类非常简单,就是相互引用了对方,也就是我们常常的说的循环依赖,spring是允许这样的循环依赖。
     
      前提是1.单例的情况下的,2.非构造方法注入的情况下
     
    
spring默认是支持循序依赖的,但是仅仅是单例的类才可以。
上面代码从容器中能正常获取到bean,说明循环依赖成功。
但是spring的循环依赖其实是可以关闭的,spring提供了api来关闭循环依赖的功能。
spring也可以关闭循环依赖:
     “`java public class SpringTest {
     
    
public static void main(String[] args) {
    AnnotationConfigApplicationContext context 
                        = new AnnotationConfigApplicationContext();
    //获取bean工厂
    DefaultListableBeanFactory beanFactory = 
                (DefaultListableBeanFactory) context.getBeanFactory();
    //关闭循环依赖
    beanFactory.setAllowCircularReferences(false);
    context.register(Config.class);
    context.refresh();
    System.out.println(context.getBean("orderService"));
}} “`
运行上面的代码,就会报错
     
    
那么为什么setAllowCircularReferences(false);会关闭循环依赖呢?
首要明白spring的循环依赖是怎么做到的呢?spring源码当中是如何处理循环依赖的?
分析一下所谓的循环依赖其实无非就是属性注入,或者就是大家常常说的自动注入, 故而搞明白循环依赖就需要去研究spring自动注入的源码。
Spring的属性注入属于spring bean的生命周期一部分;怎么理解spring bean的生命周期呢?
注意笔者这里并不打算对bean的生命周期大书特书,只是需要读者理解生命周期的概念,细节下一篇文章再写。
     解决循环依赖的2个前提
    
     单例
    
     非构造方法注入
    
     Spring循环依赖不能解决的问题
    
     不支持多例
    
     不支持构造方法注入的bean
    
     如何解决循环依赖
    
     1.\@Autowired自动注入
    
“`java @Component public class A { @Autowired B b; }
@Component public class B { @Autowired A a; } “`
     2.set方法注入
    
“`java @Component public class A1 { B1 b; @Autowired public void setB1(B1 b) { this.b = b; } }
@Component public class B1 { A1 a; @Autowired public void setA(A1 a) { this.a = a; } } “`
     3.构造方法循环依赖@Lazy
    
     
      java @Component public class C { D d; public C(@Lazy D d) { this.d = d; } }  @Component public class D { C c; public D(@Lazy C c) { this.c = c; } } 
     
     4.构造方法循环依赖无法解决
    
     5.多例循环依赖无法解决
    
     6.解决循环依赖的关键是能够提前暴露对象
    
 
