spring-bean的循环依赖以及解决方式
spring-bean的循环依赖以及解决方式
参考博客: https://blog.csdn.net/u010853261/article/details/77940767
https://blog.csdn.net/qq924862077/article/details/73926268
主要解决方式:使用三级缓存
singletonObjects: 一级缓存, Cache of singleton objects: bean name --> bean instance
earlySingletonObjects: 二级缓存, Cache of early singleton objects: bean name --> bean instance 提前曝光的BEAN缓存
singletonFactories: 三级缓存, Cache of singleton factories: bean name --> ObjectFactory
源码片段如下:
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean
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的循环依赖