接上文中对涉及到循环引用的3个方法作了陈述。
在方法1中,对象信息对beanFactory的形式被放入singletonFactories中,这时earlySingletonObjects中肯定没有此对象(因为remove)。
在方法2中,在一定条件下(allowEarlyReference为true)的条件下,对象从singleFactories中的objectFactory中被取出来,同时remove掉,被放入earlySingletonObjects中。这时,earlySingletonObjects就持有对象信息了;当然,如果allowEarlyReference为false的情况下,且earlySingletonObjects本身就没有持有对象的情况下,肯定不会将对象从objectFactory中取出来的。这个很重要,因为后面将根据此信息进行循环引用处理。
在方法3中,对象被加入到singletonObjects中,同时singletonFactories和earlySingletonObjects中都remove掉持有的对象(不管持有与否),这就表示在之前的处理中,这只相当于一个临时容器,处理完毕之后都会remove掉。
那么,我们来看这3个方法是不是按照先后顺序被调用的呢。代码顺序如下所示:
类AbstracBeanFactory获取bean。M-1
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } …… }
进入getSingleton方法M-2
Object singletonObject = this.singletonObjects.get(beanName); try { //首先执行getObject方法,再执行finnaly中的addSingleton方法,即上文中的方法3 singletonObject = singletonFactory.getObject(); }finally { addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
查看singletonFactory.getObject(),即createBean(beanName, mbd, args),最终转向doCreateBean方法M-3
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. BeanWrapper instanceWrapper = null; instanceWrapper = createBeanInstance(beanName, mbd, args); addSingletonFactory(beanName, new ObjectFactory() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
上面代码会调用方法addSingletonFactory,即上文所说的方法1。
那么方法2会在什么地方调用呢。答案在两个地点。
第一个地方,称之为调用点A,即在最开始获取bean时,会调用。
Object sharedInstance = getSingleton(beanName);
此方法最终会调用到
getSingleton(beanName, true)
这里传递了参数true。即会尝试解析singletonFactories。然而,在最开始创建对象时,singletonFactories中肯定不会持有对象信息,所以会返回null。
第二个地方,称之为调用点B,即在完成bean创建时,会有一个验证过程。即在方法M-3中,即在调用方法2之前。代码如下:
if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw 文章开头的异常。 } } }
调用点B的逻辑有点多,后面的逻辑主要是作循环引用验证。注意在调用点B传递参数为false,即不会解析singletonFactories。
详细见下一篇
Spring中循环引用的处理-3
前一篇
Spring中循环引用的处理-1
转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201208280002.html
我特意去翻了翻代码比对一下,建议省略的地方用*号表示
原文:
【在方法2中,在一定条件下(allowEarlyReference为true)的条件下,对象从singleFactories中的objectFactory中被取出来】
一下子没反应过来,singleFactories是啥~,我在源码中也没找到。
你应该是想说 : singletonFactories 对吗?
不知道博主是看的哪个版本的spring,我再源码中有的都找不到