/** * Callback before singleton creation. * <p>The default implementation register the singleton as currently in creation. * @param beanName the name of the singleton about to be created * @see #isSingletonCurrentlyInCreation */ protectedvoidbeforeSingletonCreation(String beanName) { // inCreationCheckExclusions 集合通常用于存储那些在创建检查(循环依赖检查)时需要排除的 bean 名称。如果当前 bean 名称在 inCreationCheckExclusions 中,则不满足条件 // singletonsCurrentlyInCreation 集合用于记录当前正在创建的单例 bean 的名称。如果添加当前 bean 的名称失败(即已经存在,说明当前 bean 正在创建的过程中),则不满足条件 if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { thrownewBeanCurrentlyInCreationException(beanName); } }
Prototype情况
1 2 3 4 5 6 7 8 9
// TODO 4. 原型模式的依赖检查 // 只有在单例情况才会尝试解决循环依赖 // 在原型模式下,如果存在A中有B的属性,B中有A的属性, // 那么当依赖注入的时候,就会产生还未创建完的时候因为对B创建再次返回创建A,造成循环依赖,即下述情况 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { thrownewBeanCurrentlyInCreationException(beanName); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
if (mbd.isPrototype()) { // 以prototype模式来创建bean // It's a prototype -> create a new instance. ObjectprototypeInstance=null; try { // 将beanName放入正在创建的列表中 beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { // 将beanName从正在创建的列表中移除 afterPrototypeCreation(beanName); } beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
// Eagerly check singleton cache for manually registered singletons. ObjectsharedInstance= getSingleton(beanName); // ... 省略 } /** * Return the (raw) singleton object registered under the given name. * <p>Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 从singletonObjects一级缓存中获取实例 ObjectsingletonObject=this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 从earlySingletonObjects二级缓存中获取实例 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 从singletonFactories三级缓存中获取实例 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); // 加入到二级缓存中 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
protected <T> T doGetBean(final String name, @Nullablefinal Class<T> requiredType, @Nullablefinal Object[] args, boolean typeCheckOnly)throws BeansException { // ...省略 // Create bean instance. if (mbd.isSingleton()) { // 分两步: // 1. createBean-->doCreateBean-->addSingletonFactory加入到三级缓存中 // 2. getSingleton-->addSingleton加入到一级缓存中 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // ...省略 }
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final@Nullable Object[] args) throws BeanCreationException { // ...省略 // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. booleanearlySingletonExposure= (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); // 提前暴露 if (earlySingletonExposure) { // ...省略 // 加入到三级缓存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // ...省略 } /** * Add the given singleton factory for building the specified singleton * if necessary. * <p>To be called for eager registration of singletons, e.g. to be able to * resolve circular references. * @param beanName the name of the bean * @param singletonFactory the factory for the singleton object */ protectedvoidaddSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { // 若一级缓存中没有 if (!this.singletonObjects.containsKey(beanName)) { // 加入到三级缓存中 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
/** * Return the (raw) singleton object registered under the given name, * creating and registering a new one if none registered yet. * @param beanName the name of the bean * @param singletonFactory the ObjectFactory to lazily create the singleton * with, if necessary * @return the registered singleton object */ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { ObjectsingletonObject=this.singletonObjects.get(beanName); if (singletonObject == null) { // ...省略 beforeSingletonCreation(beanName); booleannewSingleton=false; booleanrecordSuppressedExceptions= (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = newLinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } // ...省略 if (newSingleton) { // 实例创建完成后加入到一级缓存中 addSingleton(beanName, singletonObject); } } return singletonObject; } }
启动报错Requested bean is currently in creation: Is there an unresolvable circular reference?
单例的代理对象Setter注入
这种注入方式其实也比较常用,比如平时使用:@Async注解的场景,会通过AOP自动生成代理对象
1 2 3 4 5 6 7 8 9 10
@Service publicclassTestService1 {
@Autowired private TestService2 testService2;
@Async publicvoidtest1() { } }
1 2 3 4 5 6 7 8 9
@Service publicclassTestService2 {
@Autowired private TestService1 testService1;
publicvoidtest2() { } }
1
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testService1': Bean with name 'testService1' has been injected into other beans [testService2] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.