[转]spring 学习-bean创建-循环依赖-2
Posted float123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[转]spring 学习-bean创建-循环依赖-2相关的知识,希望对你有一定的参考价值。
接上文中对涉及到循环引用的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 学习-bean创建-循环依赖-2的主要内容,如果未能解决你的问题,请参考以下文章