zoukankan      html  css  js  c++  java
  • 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();
     
  • 相关阅读:
    [转]IUnkown生命周期管理
    [转] com 基本数据类型
    Centos 7 修改开机等待时间 Alex
    乌班图的安装常用命令 Alex
    Ubuntu切换root用户 Alex
    乌班图开启关闭防火墙 Alex
    Ubuntu远程root用户登录 Alex
    Centos 8 更改为阿里云源 Alex
    LVS调度之搭建NAT模型实现 Alex
    解决挂载mount: wrong fs type, bad option, bad superblock on Alex
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/10638445.html
Copyright © 2011-2022 走看看