spring-bean的循環依賴以及解決方式

spring-bean的循環依賴以及解決方式

參考博客: http://www.javashuo.com/article/p-qnshsajb-bg.htmlspring

https://blog.csdn.net/qq924862077/article/details/73926268緩存

主要解決方式:使用三級緩存ide

singletonObjects: 一級緩存, Cache of singleton objects: bean name --> bean instanceui

earlySingletonObjects: 二級緩存, Cache of early singleton objects: bean name --> bean instance  提早曝光的BEAN緩存this

singletonFactories: 三級緩存, Cache of singleton factories: bean name --> ObjectFactoryspa

源碼片斷以下:.net

org.springframework.beans.factory.support.AbstractBeanFactory.doGetBeanprototype

複製代碼
  1 protected <T> T doGetBean(  2 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  3 throws BeansException {  4  5 final String beanName = transformedBeanName(name);  6  Object bean;  7  8 // Eagerly check singleton cache for manually registered singletons.  9 Object sharedInstance = getSingleton(beanName);  10 if (sharedInstance != null && args == null) {  11 if (logger.isDebugEnabled()) {  12 if (isSingletonCurrentlyInCreation(beanName)) {  13 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +  14 "' that is not fully initialized yet - a consequence of a circular reference");  15  }  16 else {  17 logger.debug("Returning cached instance of singleton bean '" + beanName + "'");  18  }  19  }  20 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  21  }  22  23 else {  24 // Fail if we're already creating this bean instance:  25 // We're assumably within a circular reference.  26 if (isPrototypeCurrentlyInCreation(beanName)) {  27 throw new BeanCurrentlyInCreationException(beanName);  28  }  29  30 // Check if bean definition exists in this factory.  31 BeanFactory parentBeanFactory = getParentBeanFactory();  32 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  33 // Not found -> check parent.  34 String nameToLookup = originalBeanName(name);  35 if (args != null) {  36 // Delegation to parent with explicit args.  37 return (T) parentBeanFactory.getBean(nameToLookup, args);  38  }  39 else {  40 // No args -> delegate to standard getBean method.  41 return parentBeanFactory.getBean(nameToLookup, requiredType);  42  }  43  }  44  45 if (!typeCheckOnly) {  46  markBeanAsCreated(beanName);  47  }  48  49 try {  50 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  51  checkMergedBeanDefinition(mbd, beanName, args);  52  53 // Guarantee initialization of beans that the current bean depends on.  54 String[] dependsOn = mbd.getDependsOn();  55 if (dependsOn != null) {  56 for (String dep : dependsOn) {  57 if (isDependent(beanName, dep)) {  58 throw new BeanCreationException(mbd.getResourceDescription(), beanName,  59 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");  60  }  61  registerDependentBean(dep, beanName);  62  getBean(dep);  63  }  64  }  65  66 // Create bean instance.  67 if (mbd.isSingleton()) {  68 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {  69  @Override  70 public Object getObject() throws BeansException {  71 try {  72 return createBean(beanName, mbd, args);  73  }  74 catch (BeansException ex) {  75 // Explicitly remove instance from singleton cache: It might have been put there  76 // eagerly by the creation process, to allow for circular reference resolution.  77 // Also remove any beans that received a temporary reference to the bean. 78 destroySingleton(beanName); 79 throw ex; 80 } 81 } 82 }); 83 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 84 } 85 86 else if (mbd.isPrototype()) { 87 // It's a prototype -> create a new instance. 88 Object prototypeInstance = null; 89 try { 90 beforePrototypeCreation(beanName); 91 prototypeInstance = createBean(beanName, mbd, args); 92 } 93 finally { 94 afterPrototypeCreation(beanName); 95 } 96 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 97 } 98 99 else { 100 String scopeName = mbd.getScope(); 101 final Scope scope = this.scopes.get(scopeName); 102 if (scope == null) { 103 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); 104 } 105 try { 106 Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { 107 @Override 108 public Object getObject() throws BeansException { 109 beforePrototypeCreation(beanName); 110 try { 111 return createBean(beanName, mbd, args); 112 } 113 finally { 114 afterPrototypeCreation(beanName); 115 } 116 } 117 }); 118 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 119 } 120 catch (IllegalStateException ex) { 121 throw new BeanCreationException(beanName, 122 "Scope '" + scopeName + "' is not active for the current thread; consider " + 123 "defining a scoped proxy for this bean if you intend to refer to it from a singleton", 124 ex); 125 } 126 } 127 } 128 catch (BeansException ex) { 129 cleanupAfterBeanCreationFailure(beanName); 130 throw ex; 131 } 132 } 133 134 // Check if required type matches the type of the actual bean instance. 135 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { 136 try { 137 return getTypeConverter().convertIfNecessary(bean, requiredType); 138 } 139 catch (TypeMismatchException ex) { 140 if (logger.isDebugEnabled()) { 141 logger.debug("Failed to convert bean '" + name + "' to required type '" + 142 ClassUtils.getQualifiedName(requiredType) + "'", ex); 143 } 144 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 145 } 146 } 147 return (T) bean; 148 }
複製代碼

 總結:簡單來講Spring不支持原型bean的循環依賴debug

相關文章
相關標籤/搜索