spring主要处理的是属性注入的循环依赖,即beanA的属性中有beanB,beanB的属性中有beanA。
而其主要的解决方式则是在创建beanA但是还有没有对beanA进行赋值之前先将beanA的索引注册到容器中,而在beanA进行属性赋值时会引起beanB的创建操作,而在beanB的创建过程中需要进行属性赋值,而其获取beanA的属性值则是获取的beanA先暴露到容器的对象。
下面来详细描述一下上面那段解释,首先写一个循环依赖的例子:
@Component
public class CircleA {
@Autowired
public CircleB circleB ;
public void test() {
System.out.println(circleB) ;
}
}
@Component
public class CircleB {
@Autowired
public CircleA circleA ;
public void test() {
System.out.println(circleA) ;
}
}
public class TestCircle {
public static void main(String[] args) {
ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext(new String[] {"classpath:spring-circle.xml"},false) ;
application.refresh();
CircleA circleA = application.getBean(CircleA.class) ;
System.out.println(circleA) ;
circleA.test();
System.out.println("===========================") ;
CircleB circleB = application.getBean(CircleB.class) ;
System.out.println(circleB) ;
circleB.test();
System.out.println(circleA.circleB == circleB) ;
System.out.println(circleB.circleA == circleA) ;
}
}
/*================输出=============
com.test.spring.circle.CircleA@1efee8e7
com.test.spring.circle.CircleB@1ee807c6
===========================
com.test.spring.circle.CircleB@1ee807c6
com.test.spring.circle.CircleA@1efee8e7
true
true
*/
上面的代码清单描述了一个简单的循环依赖情况,CircleA中有CircleB的属性,而CircleB中有CircleA中的属性。
下面这个图是从容器中获取circleA的调用栈,可以看到它是先调用了DefaultListableBeanFactory#getBean方法来获取circleA,circleA在进行创建过程中调用了populateBean方法来进行属性的注入,而在注入过程中由于依赖circleB,所以又调用了getBean方法获取circleB,而circleB在创建过程中由于依赖CircleA而再次调用getBean方法获取circleA,但是这次circleA没有继续进行创建操作,因为之前circleA已经将其对象索引通过ObjectFactory注册到容器中了,所以这次getBean的方法最终调用的getSingleton的方法与之前的getSingleton方法有所不同,是173行的方法。
上面的调用栈中可以看到前面两次调用对应getSingleton()都是230行的,最后一次是173行的,下面来分析一下这两个getSIngleton方法先看230行对应的getSingleton()方法。
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
... throws
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
...
try {
//#####获取bean实例的方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
...
}
finally {
...
afterSingletonCreation(beanName);
}
if (newSingleton) {
//注册到singletonObjects中
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
上面的代码清单很清单,先从singletonObjects这个map中找对应的实例,找不到则利用ObjectFactory获取对应的实例,并将获取的实例注册到singletonObjects中。
对于上面的例子来说circleA和circleB在刚开始在容器都没有数据,则都会利用singletonFactory进行创建。而这个singletonFactory最终调用了DefaultListableBeanFactory的createBean方法来进行bean的创建。
上面的例子中它在创建circleA的过程中会在circleA实例化后先将circleA的实例利用ObjectFacotry注册到容器中。其具体操作是在AbstractAutowireCapableBeanFactory的doCreateBean进行操作的。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化circleA
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
...
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//将circleA的实例注册到DefaultSingletonBeanRegistry中
addSingletonFactory(beanName, new ObjectFactory
上面这段代码描述了在实例化circleA之后,在对circleA进行属性注册(实例化circleB)之前进行了一项操作,即将circleA以ObjectFactory的形式注册到了DefaultSingletonBeanRegistry中。最终circleB在属性注入的时候则不需要进行circleA的创建,而是从ObjectFactory中直接获取circleA的实例。其具体获取的方式则是在173行的getSingleton方法中。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//circleA注册进入的beanFactory,最终获取的是刚开始创建的circleA的实例
//再进行包装的对象
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
上面的代码可以看到其获取实例的方式是先从singletonObjects中获取对应的bean,如果没有获取则是从earlySingletonObjects中获取bean