• 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();
     
  • 相关阅读:
    批处理命令之实现修改环境变量的值
    【hihocoder 1304】搜索一·24点
    【hihocoder 1297】数论四·扩展欧几里德
    【hihocoder 1298】 数论五·欧拉函数
    【hihocoder 1303】模线性方程组
    C语言如何动态分配二维数组
    Istream中的函数
    string 与 char * 转换
    boost 系列 1:boost 直接使用
    glog功能介绍 一分钟 51CTO技术博客
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/10638445.html
Copyright © 2020-2023  润新知