Spring解决循环依赖

1.Spring解决循环依赖

什么是循环依赖:比如A引用B,B引用C,C引用A,它们最终形成一个依赖环。

循环依赖有两种
  1、构造器循环依赖

    构造器注入导致的循环依赖,Spring是无法解决的,只能抛出BeanCurrentlyInCreationException异常。因为构造器注入时的参数需要依赖bean的实例。所以无法解决循环依赖的问题。

    如在创建A的实例时,发现依赖B,那将去创建B的实例,又发现依赖C,则又去创建C,最终在创建C的时候发现依赖A,从而形成一个环,没办法创建。

    Spring容器每一个正在创建的bean标识符放在一个“当前创建bean池”中,这个池是一个set集合

private final Set<String> singletonsCurrentlyInCreation = Collections.synchronizedSet(new HashSet());

    bean标识符将一直保持在这个池中,因此如果bean创建过程中发现自己已经在当前创建bean池中时,将抛出BeanCurrentlyInCreationException异常表示循环依赖。而对于创建完毕的bean将从“当前创建bean”池中清除掉。

    

  2、setter循环依赖

    表示通过setter注入方式构成的循环依赖。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器创建实例但未完成其他步骤如setter注入的bean来完成的。提前暴露一个

    单例工厂方法,从而使其他bean能引用该bean。

    而且只能解决单例作用域的bean循环依赖。

    步骤:

    1、Spring容器创建单例A bean,首先通过无参构造器创建bean,并暴露一个ObjectFactory返回一个在创建中的bean,并将A标识符放在当前创建bean池中。然后通过setter方式注入

    依赖B

    2、Spring容器创建单例B bean,首先通过无参构造器创建bean,并暴露一个ObjectFactory返回一个在创建中的bean,并将B标识符放在当前创建bean池中。然后通过setter方式注入

    依赖C

    3、Spring容器创建单例C bean,首先通过无参构造器创建bean,并暴露一个ObjectFactory返回一个正在创建中的bean,并将C标识符放在当前创建bean池中。然后setter方式

    注入A,进行注入A时由于提前暴露了ObjectFactory工厂,所以使用它返回提前暴露一个创建中的bean。

    4.然后再依次完成setter注入C完成B创建,依赖注入B完成A创建。

    prototype范围的依赖处理:spring也无法完成依赖注入,因为Spring容器不进行缓存prototype作用域的bean,因此无法暴露一个创建中的bean。(单例范围下是通过放入缓存中的ObjectFactory来创建实例)

    缓存objectFactory是将ObjectFactory放入map中

private final Map<String, ObjectFactory> singletonFactories = new HashMap();

this.singletonFactories.put(beanName, singletonFactory);

this.addSingletonFactory(beanName, new ObjectFactory() {
                public Object getObject() throws BeansException {
// 在此完成aop动态织入
                    return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
                }
            });

   aop将advice动态织入bean中也是在将创建bean的工厂放在单例工厂集合中时织入的。

  常规bean的创建是在AbstratAutowireCapableBeanFactory的doCreateBean方法中创建的。
  创建完成的bean,如果配置了destory-method则放在LinkHashMap中,便于在销毁时调用。
private final Map<String, Object> disposableBeans = new LinkedHashMap();
 
原文地址:https://www.cnblogs.com/yangyongjie/p/10638445.html