博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring注入与循环依赖
阅读量:5835 次
发布时间:2019-06-18

本文共 2833 字,大约阅读时间需要 9 分钟。

hot3.png

Spring中如何解决循环依赖,简单举个下面这样例子

  • A类中注入了B类对象
  • B类中注入了A类对象

 如果是通过构造函数注入,那么在初始化时的时候会报循环注入。A初始化时B可能尚未初始化。

反之,如果是通过get set这种注入或者@Autowired 注入,并且是singelton(默认)而非prototype则不会报错。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单例作用域的bean循环依赖。spring通过提前暴露一个单例工厂方法,从而使其他bean能引用到该bean。

protected void beforeSingletonCreation(String beanName) {          if (!this.inCreationCheckExclusions.containsKey(beanName)                  && this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) {              throw new BeanCurrentlyInCreationException(beanName);          }      }

1.从源码中可以看出,A实例化时会去singletonsCurrentlyInCreation写入A,A中依赖B因此,需要实例化B,B中依赖A,因此需要实例A,而A之前已经在Increation,因此会报错。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {        // Instantiate the bean.        //.....        // Eagerly cache singletons to be able to resolve circular references        // even when triggered by lifecycle interfaces like BeanFactoryAware.        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&                isSingletonCurrentlyInCreation(beanName));        if (earlySingletonExposure) {            if (logger.isDebugEnabled()) {                logger.debug("Eagerly caching bean '" + beanName +                        "' to allow for resolving potential circular references");            }            addSingletonFactory(beanName, new ObjectFactory() {                public Object getObject() throws BeansException {                    return getEarlyBeanReference(beanName, mbd, bean);                }            });        }        // ......    }protected Object getSingleton(String beanName, boolean allowEarlyReference) {                Object singletonObject = this.singletonObjects.get(beanName);        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {                        synchronized (singletonObject) {                singletonObject = this.earlySingletonObjects.get(beanName);                                 if (singletonObject == null && allowEarlyReference) {                                         ObjectFactory objectFactory = this.singletonFactories.get(beanName);                    if (objectFactory != null) {                        singletonObject = objectFactory.getObject();                        this.earlySingletonObjects.put(beanName, singletonObject);                        this.singletonFactories.remove(beanName);                    }                }            }        }        return (singletonObject != NULL_OBJECT) ? singletonObject : null;    }

2.采用set方法时,Spring略有不同,A实例化时会将一个 A的实例引用写入objectFactory中。执行setB时去实例化B,B的setA调用getSingleton(A,true),因为A 实例还在创建中,会接着往下执行,最终通过objectFactory返回A的实例引用,之后删除factory,缓存A的引用。

 

转载于:https://my.oschina.net/u/2433649/blog/823794

你可能感兴趣的文章
直播源码开发视频直播平台,不得不了解的流程
查看>>
Ubuntu上的pycrypto给出了编译器错误
查看>>
聊聊flink的RestClientConfiguration
查看>>
在CentOS上搭建git仓库服务器以及mac端进行克隆和提交到远程git仓库
查看>>
測試文章
查看>>
Flex很难?一文就足够了
查看>>
【BATJ面试必会】JAVA面试到底需要掌握什么?【上】
查看>>
CollabNet_Subversion小结
查看>>
mysql定时备份自动上传
查看>>
17岁时少年决定把海洋洗干净,现在21岁的他做到了
查看>>
《写给大忙人看的java se 8》笔记
查看>>
倒计时:计算时间差
查看>>
Linux/windows P2V VMWare ESXi
查看>>
Windows XP倒计时到底意味着什么?
查看>>
运维工程师在干什么学些什么?【致菜鸟】
查看>>
Linux中iptables详解
查看>>
java中回调函数以及关于包装类的Demo
查看>>
maven异常:missing artifact jdk.tools:jar:1.6
查看>>
终端安全求生指南(五)-——日志管理
查看>>
Nginx 使用 openssl 的自签名证书
查看>>