1、两个都是prototype的bean
两个bean都是prototype,只有在使用的时候才去创建bean。 AbstractBeanFactory类中doGetBean方法检测循环依赖。
// Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }
/** * Return whether the specified prototype bean is currently in creation * (within the current thread). * @param beanName the name of the bean */ protected boolean isPrototypeCurrentlyInCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); return (curVal != null && (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); }
else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
protected void beforePrototypeCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); if (curVal == null) { this.prototypesCurrentlyInCreation.set(beanName); } else if (curVal instanceof String) { Set<String> beanNameSet = new HashSet<String>(2); beanNameSet.add((String) curVal); beanNameSet.add(beanName); this.prototypesCurrentlyInCreation.set(beanNameSet); } else { Set<String> beanNameSet = (Set<String>) curVal; beanNameSet.add(beanName); } }
protected void afterPrototypeCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); if (curVal instanceof String) { this.prototypesCurrentlyInCreation.remove(); } else if (curVal instanceof Set) { Set<String> beanNameSet = (Set<String>) curVal; beanNameSet.remove(beanName); if (beanNameSet.isEmpty()) { this.prototypesCurrentlyInCreation.remove(); } } }两个bean代码如下
@Component @Scope("prototype") public class BeanN1 { @Autowired private BeanN2 beanN2; @PostConstruct public void init() { System.out.println(beanN2); } }
@Component @Scope("prototype") public class BeanN2 { @Autowired private BeanN1 beanN1; @PostConstruct public void init() { System.out.println(beanN1); } }
启动之后获得bean
public static void main(String[] args) { //负责启动引导应用程序 ConfigurableApplicationContext run = SpringApplication.run(SpringBootDemoApplication.class, args); BeanN1 bean = run.getBean(BeanN1.class); System.out.println(bean); }
报如下错误:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanN1': Requested bean is currently in creation: Is there an unresolvable circular reference?当获取BeanN1的时候,开始创建BeanN1,首先isPrototypeCurrentlyInCreation方法检测是否是循环依赖,prototypesCurrentlyInCreation里面是null,继续往下走,在创建BeanN1之前将beanN1放入 prototypesCurrentlyInCreation中,此时prototypesCurrentlyInCreation是一个String类型,值是beanN1,因为beanN1依赖BeanN2,开始创建BeanN2,首先isPrototypeCurrentlyInCreation方法检测是否是循环依赖,prototypesCurrentlyInCreation里面是beanN1,继续往下走,在创建BeanN2之前将beanN2放入prototypesCurrentlyInCreation中,此时prototypesCurrentlyInCreation是一个Set类型,值是beanN1、beanN2,因为BeanN2依赖BeanN1,又需要创建BeanN1,当调用isPrototypeCurrentlyInCreation方法检测是否是循环依赖,prototypesCurrentlyInCreation里面是beanN1、beanN2,当前创建的是beanN1,所以检测出了循环依赖,直接抛出异常。
2.两个bean 一个Singleton一个prototype
@Component @Scope("prototype") public class BeanN1 { @Autowired private BeanN2 beanN2; @PostConstruct public void init() { System.out.println("BeanN1初始化:" + beanN2); } }
@Component public class BeanN2 { @Autowired private BeanN1 beanN1; @PostConstruct public void init() { System.out.println("beanN2初始化:"); System.out.println(beanN1); System.out.println(this); } }
启动的时候看到输出如下:
BeanN1初始化:com.zhp.cyclic.dependency.BeanN2@602f8f94
beanN2初始化:
com.zhp.cyclic.dependency.BeanN1@42507640
com.zhp.cyclic.dependency.BeanN2@602f8f94
beanN2初始化:
com.zhp.cyclic.dependency.BeanN1@42507640
com.zhp.cyclic.dependency.BeanN2@602f8f94
因为beanN2是Singleton,启动的时候创建BeanN2对象,然后放入对象池中。
// Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }然后解析BeanN2的依赖,它依赖BeanN1,BeanN1是prototype,开始创建BeanN1,BeanN1依赖BeanN2,直接从对象池中获取即可,BeanN1初始化完成。
// Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); getBean(dep); } }BeanN1初始化完成之后, BeanN2也就可以正确的初始化了。
启动之后执行如下代码:
BeanN1 bean = run.getBean(BeanN1.class); System.out.println(bean);输出
BeanN1初始化:com.zhp.cyclic.dependency.BeanN2@602f8f94
com.zhp.cyclic.dependency.BeanN1@77083e41
com.zhp.cyclic.dependency.BeanN1@77083e41
我们看到BeanN2是单例,对象没变,BeanN1变了。和BeanN2中的BeanN1是不一样的。com.zhp.cyclic.dependency.BeanN1@42507640
3.两个对象都是Singleton
这种循环依赖是没问题的,完全可以创建成功。因为都是先创建对象,放入对象池,然后才组装依赖对象。