• Spring源码分析 循环依赖 三级缓存


    本文目的

    本文主要说明什么是Spring的循环依赖。哪些场景的循环依赖Spring可以解决。如何解决的。同时讲解了Spring的三级缓存。

    类图

    A
    B b
    +getB()
    +setB()
    B
    A a
    +getA()
    +setA()

    什么是循环依赖

    参考上面的类图,Spring要初始化A类,但A类中有一个类型为B的属性,所以此时要去创建类型B。但是B类中又有一个A类型的属性,所以反过来又需要初始化A,但A此时又没有初始化完成。这就是循环依赖问题。

    这个例子中说的是AB型循环依赖,还有ABC型。就是A中有B,B中有C,但C中又有A。

    如果不考虑Spring,循环依赖其实并不是问题,因为对象之间相互依赖是很正常的事情。但在Spring中,一个对象并不是简单new出来就可以了,而是会经过一系列的Bean的生命周期。正式因为Beand生命周期的存在,才会出现循环依赖问题。所以建议大家可以先了解下Bean的生命周期

    如何解决

    首先并不是所有场景的循环依赖Spring都能解决的。Spring只能解决单例对象且set方法的循环依赖。构造器或者多例对象目前Spring无法解决。这种情况需要程序员自己避免或者向其他办法解决。

    接下来正式介绍Spring解决循环依赖的机制,叫做三级缓存

    Spring三级缓存

    三级缓存说穿了,其实就是Spring中一个类的三个Map,

    • 一级缓存:singletonObjects;
    • 二级缓存为:earlySingletonObjects;
    • 三级缓存为:singletonFactories;

    类名:DefaultSingletonBeanRegistry,源码参考如下:

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
    	/**
    	 * 一级缓存
    	 * 用于保存BeanName和创建bean实例之间的关系
    	 *
    	 * Cache of singleton objects: bean name to bean instance. */
    	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    	/**
    	 * 三级缓存
    	 * 用于保存BeanName和创建bean的工厂之间的关系
    	 *
    	 * Cache of singleton factories: bean name to ObjectFactory. */
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    	/**
    	 * 二级缓存
    	 * 保存BeanName和创建bean实例之间的关系,与singletonFactories的不同之处在于,当一个单例bean被放到这里之后,那么当
    	 * bean还在创建过程中,就可以通过getBean方法获取到,可以方便进行循环依赖的检测
    	 *
    	 * Cache of early singleton objects: bean name to bean instance. */
    	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    三个缓存分别放的是什么?

    一级缓存(singletonObjects)中放的是已经初始化完成的bean对象。

    二级缓存(earlySingletonObjects)比 singletonObjects 多了一个 early,表示存放的是实例化结束但还没初始化的bean对象。

    三级缓存(singletonFactories)中存的是ObjectFactory,表示的是用来创建AOP代理对象的函数式接口。

    如果只有二级缓存

    如果不考虑AOP对象代理,其实只需要二级缓存足以解决问题。

    我们先使用二级缓存来把解决流程演示一遍。

    1. 首先创建A的Bean对象,先依次在一二三级缓存中找。显然第一次肯定是找不到。
    2. 然后开始实例化A,实例化A结束后,会将A对象放入二级缓存中。此时A还没初始化。
    3. 然后进行属性赋值,遇到B对象。
    4. 同样的流程,先依次在一二三级缓存找。肯定也是找不到。
    5. 开始实例化B,实例化B结束,放入二级缓存中。此时B也没初始化。
    6. 然后进行属性赋值,遇到A对象。也是依次在一二三级缓存找
    7. 此时由于A对象已经在二级缓存中存在,所以找到后,完成B的属性赋值
    8. 接着继续B的初始化,然后初始化完成之后,放入一级缓存中。
    9. 接着A的属性赋值和初始化也能结束了。放入一级缓存中。
    10. 下面是用mermaid画的流程图。
    B
    A
    三级缓存
    A
    B
    B创建完成
    初始化B
    在二级缓存中找到A
    去一、二、三级缓存中查找a
    属性赋值A
    放入二级缓存
    实例化B
    没有找到B
    在一、二、三级缓存中查找B
    A创建完成
    初始化A
    属性赋值B
    放入二级缓存
    实例化A
    没有找到A
    在一、二、三级缓存中查找A
    三级缓存
    二级缓存
    一级缓存

    代理和三级缓存

    既然二级缓存就能解决循环依赖,那为什么考虑了AOP代理之后就必须使用三级缓存了呢?首先要了解的一个知识就是Spring的AOP代理对象的产生是在填充属性后进入到初始化阶段才进行的,是通过后置处理器BeanPostProcessor来实现。如果用二级缓存来解决,那么就要在属性填充的时候,就要将代理对象生成好,放入二级缓存了。那这样就与Spring的Bean生命周期相悖了。所以这种方式不好,于是就引入了三级缓存以及ObjectFactory对象。

    引入了三级缓存之后的流程。

    1. 首先创建A的Bean对象,先依次在一二三级缓存中找。显然第一次肯定是找不到。
    2. 然后开始实例化A,实例化A结束后,那此时会将A放入三级缓存而不是二级缓存
    3. 放入三级缓存中的A是一个函数式接口ObjectFactory对象。此时并没有调用接口方法
    4. 然后进行属性赋值,遇到B对象。
    5. 同样的流程,先依次在一二三级缓存找。肯定也是找不到。
    6. 开始实例化B,实例化B结束,同样将ObjectFactory放入三级缓存中。
    7. 然后进行属性赋值,遇到A对象。也是依次在一二三级缓存找。
    8. 此时可以在三级缓存中找到A的ObjectFactory对象,找到后会调用ObjectFactory.getObject()方法,
    9. 将生成的代理对象放到二级缓存中。同时删除三级缓存中的对象。
    10. 接着继续B的初始化,然后初始化完成之后,放入一级缓存中。
    11. 接着A的属性赋值和初始化也能结束了。放入一级缓存中。
    B
    A
    三级缓存
    ObjectFactory(A)
    ObjectFactory(B)
    B创建完成
    初始化B
    通过ObjectFactory的getObject()
    得到对象然后移入二级缓存
    在三级缓存中找到ObjectFactory(A)
    去一、二、三级缓存中查找a
    属性赋值A
    放入三级缓存
    实例化B
    没有找到B
    在一、二、三级缓存中查找B
    A创建完成
    初始化A
    属性赋值B
    放入三级缓存
    实例化A
    没有找到A
    在一、二、三级缓存中查找A
    三级缓存
    二级缓存
    一级缓存

    二级缓存在其中的作用

    假设AB相互依赖,AC相互依赖。那么B实例化后,就该进行C的实例化,这时C就可以从二级缓存来获取A的实例引用了,就不需要再从三级缓存获取工厂让其生产实例。

    即假设只有AB相互依赖,其他对象不依赖AB时,这里二级缓存是没用的,一级和三级缓存起作用。

    源码分析

    接下来我们可以从Spring源码中印证上述想法的正确性。

    创建对象之前先从缓存中查找

    AbstractBeanFactory.doGetBean()方法。第15行,先调用getSingleton方法去缓存中找。

    	/**
    	 * 得到一个Bean实例的实例,
    	 *
    	 */
    	protected <T> T doGetBean(
    			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    			throws BeansException {
    
    		/** 提取对应的beanName,这里需要转换的原因在于,当bean对象实现FactoryBean接口之后就会变成&beanName,同时如果存在别名,也需要把别名进行转换 */
    		String beanName = transformedBeanName(name);
    		Object bean;
    
    		// Eagerly check singleton cache for manually registered singletons.
    		/** 提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联 */
    		Object sharedInstance = getSingleton(beanName);
    		// 如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
    		if (sharedInstance != null && args == null) {
    			if (logger.isTraceEnabled()) {
    				if (isSingletonCurrentlyInCreation(beanName)) {
    					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
    							"' that is not fully initialized yet - a consequence of a circular reference");
    				}
    				else {
    					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
    				}
    			}
    			// 返回对象的实例,当你实现了FactoryBean接口的对象,需要获取具体的对象的时候就需要此方法来进行获取了
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
    
    		else {
    			// Fail if we're already creating this bean instance:
    			// We're assumably within a circular reference.
    			// 当对象都是单例的时候会尝试解决循环依赖的问题,但是原型模式下如果存在循环依赖的情况,那么直接抛出异常
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    
    			// Check if bean definition exists in this factory.
    			// 如果bean定义不存在,就检查父工厂是否有
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			// 如果beanDefinitionMap中也就是在所有已经加载的类中不包含beanName,那么就尝试从父容器中获取
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    				// Not found -> check parent.
    				// 获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
    				String nameToLookup = originalBeanName(name);
    				// 如果父工厂是AbstractBeanFactory的实例
    				if (parentBeanFactory instanceof AbstractBeanFactory) {
    					// 调用父工厂的doGetBean方法,就是该方法。【递归】
    					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    							nameToLookup, requiredType, args, typeCheckOnly);
    				}
    				else if (args != null) {
    					// Delegation to parent with explicit args.
    					// 如果有创建bean实例时要使用的参数
    					// Delegation to parent with explicit args. 使用显示参数委派给父工厂
    					// 使用父工厂获取该bean对象,通bean全类名和创建bean实例时要使用的参数
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}
    				else if (requiredType != null) {
    					// No args -> delegate to standard getBean method.
    					// 没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。
    					// 使用父工厂获取该bean对象,通bean全类名和所需的bean类型
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    				else {
    					// 使用父工厂获取bean,通过bean全类名
    					return (T) parentBeanFactory.getBean(nameToLookup);
    				}
    			}
    			// 如果不是做类型检查,那么表示要创建bean,此处在集合中做一个记录
    			if (!typeCheckOnly) {
    				// 为beanName标记为已经创建(或将要创建)
    				markBeanAsCreated(beanName);
    			}
    
    			try {
    				// 此处做了BeanDefinition对象的转换,当我们从xml文件中加载beandefinition对象的时候,封装的对象是GenericBeanDefinition,
    				// 此处要做类型转换,如果是子类bean的话,会合并父类的相关属性
    				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				// 检查mbd的合法性,不合格会引发验证异常
    				checkMergedBeanDefinition(mbd, beanName, args);
    
    				// Guarantee initialization of beans that the current bean depends on.
    				// 如果存在依赖的bean的话,那么则优先实例化依赖的bean
    				String[] dependsOn = mbd.getDependsOn();
    				if (dependsOn != null) {
    					// 如果存在依赖,则需要递归实例化依赖的bean
    					for (String dep : dependsOn) {
    						// 如果beanName已注册依赖于dependentBeanName的关系
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    						}
    						// 注册各个bean的依赖关系,方便进行销毁
    						registerDependentBean(dep, beanName);
    						try {
    							// 递归优先实例化被依赖的Bean
    							getBean(dep);
    						}
    						// 捕捉为找到BeanDefinition异常:'beanName'依赖于缺少的bean'dep'
    						catch (NoSuchBeanDefinitionException ex) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    						}
    					}
    				}
    
    				// Create bean instance.
    				// 创建bean的实例对象
    				if (mbd.isSingleton()) {
    					// 返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
    							// 为给定的合并后BeanDefinition(和参数)创建一个bean实例
    							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.
    							// 显示地从单例缓存中删除实例:它可能是由创建过程急切地放在那里,以允许循环引用解析。还要删除
    							// 接收到该Bean临时引用的任何Bean
    							// 销毁给定的bean。如果找到相应的一次性Bean实例,则委托给destoryBean
    							destroySingleton(beanName);
    							// 重新抛出ex
    							throw ex;
    						}
    					});
    					// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
    					// FactoryBean会直接返回beanInstance实例
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    				// 原型模式的bean对象创建
    				else if (mbd.isPrototype()) {
    					// It's a prototype -> create a new instance.
    					// 它是一个原型 -> 创建一个新实例
    					// 定义prototype实例
    					Object prototypeInstance = null;
    					try {
    						// 创建Prototype对象前的准备工作,默认实现将beanName添加到prototypesCurrentlyInCreation中
    						beforePrototypeCreation(beanName);
    						// 为mbd(和参数)创建一个bean实例
    						prototypeInstance = createBean(beanName, mbd, args);
    					}
    					finally {
    						// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
    						afterPrototypeCreation(beanName);
    					}
    					// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
    					// FactoryBean会直接返回beanInstance实例
    					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				}
    
    				else {
    					// 指定的scope上实例化bean
    					String scopeName = mbd.getScope();
    					if (!StringUtils.hasLength(scopeName)) {
    						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
    					}
    					// 从scopes中获取scopeName对于的Scope对象
    					Scope scope = this.scopes.get(scopeName);
    					// 如果scope为null
    					if (scope == null) {
    						// 抛出非法状态异常:没有名为'scopeName'的scope注册
    						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    					}
    					try {
    						// 从scope中获取beanName对应的实例对象
    						Object scopedInstance = scope.get(beanName, () -> {
    							// 创建Prototype对象前的准备工作,默认实现 将beanName添加到prototypesCurrentlyInCreation中
    							beforePrototypeCreation(beanName);
    							try {
    								// 为mbd(和参数)创建一个bean实例
    								return createBean(beanName, mbd, args);
    							}
    							finally {
    								// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
    								afterPrototypeCreation(beanName);
    							}
    						});
    						// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
    						// FactoryBean会直接返回beanInstance实例
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					}
    					catch (IllegalStateException ex) {
    						// 捕捉非法状态异常
    						// 抛出Bean创建异常:作用域 'scopeName' 对于当前线程是不活动的;如果您打算从单个实例引用它,请考虑为此
    						// beanDefinition一个作用域代理
    						throw new BeanCreationException(beanName,
    								"Scope '" + scopeName + "' is not active for the current thread; consider " +
    								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    								ex);
    					}
    				}
    			}
    			catch (BeansException ex) {
    				// 捕捉获取Bean对象抛出的Bean异常
    				// 在Bean创建失败后,对缓存的元数据执行适当的清理
    				cleanupAfterBeanCreationFailure(beanName);
    				// 重新抛出ex
    				throw ex;
    			}
    		}
    
    		// Check if required type matches the type of the actual bean instance.
    		// 检查requiredType是否与实际Bean实例的类型匹配
    		// 如果requiredType不为null&&bean不是requiredType的实例
    		if (requiredType != null && !requiredType.isInstance(bean)) {
    			try {
    				// 获取此BeanFactory使用的类型转换器,将bean转换为requiredType
    				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    				// 如果convertedBean为null
    				if (convertedBean == null) {
    					// 抛出Bean不是必要类型的异常
    					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    				}
    				// 返回convertedBean
    				return convertedBean;
    			}
    			catch (TypeMismatchException ex) {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Failed to convert bean '" + name + "' to required type '" +
    							ClassUtils.getQualifiedName(requiredType) + "'", ex);
    				}
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    		}
    		// 将bean返回出去
    		return (T) bean;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231

    从一二三级缓存中依次查找对象

    DefaultSingletonBeanRegistry.getSingleton()方法。从三级缓存中找到对象之后还会调用ObjectFactory的getObject()方法得到单例对象。放到二级缓存中,同时从三级缓存中移除。

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    		// Quick check for existing instance without full singleton lock
    		// 从单例对象缓存(一级缓存)中获取beanName对应的单例对象
    		Object singletonObject = this.singletonObjects.get(beanName);
    		// 如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			// 从早期单例对象缓存(二级缓存)中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
    			singletonObject = this.earlySingletonObjects.get(beanName);
    			// 如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
    			if (singletonObject == null && allowEarlyReference) {
    				// 如果为空,则锁定全局变量并进行处理
    				synchronized (this.singletonObjects) {
    					// Consistent creation of early reference within full singleton lock
    					singletonObject = this.singletonObjects.get(beanName);
    					if (singletonObject == null) {
    						singletonObject = this.earlySingletonObjects.get(beanName);
    						if (singletonObject == null) {
    							// 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
    							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    							if (singletonFactory != null) {
    								// 如果存在单例对象工厂,则通过工厂创建一个单例对象
    								singletonObject = singletonFactory.getObject();
    								// 记录在缓存中,二级缓存和三级缓存的对象不能同时存在
    								this.earlySingletonObjects.put(beanName, singletonObject);
    								// 从三级缓存中移除
    								this.singletonFactories.remove(beanName);
    							}
    						}
    					}
    				}
    			}
    		}
    		return singletonObject;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    对象实例化时放入到三级缓存中

    AbstractAutowireCapableBeanFactory.doCreateBean()方法.对于符合循环依赖条件的bean,会往三级缓存中放入一个lambda表达式返回的ObjectFactory对象

    // ... 省略非关键代码
    // 判断当前bean是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖	
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                //实例化后的对象先添加到三级缓存中,三级缓存对应beanName的是一个lambda表达式(能够触发创建代理对象的机制)
                this.singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
                this.registeredSingletons.add(beanName);
            }
        }
    
    }
    
    // Initialize the bean instance.
    // 初始化bean实例
    Object exposedObject = bean;
    try {
        // 对bean的属性进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean
        populateBean(beanName, mbd, instanceWrapper);
        // 执行初始化逻辑
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    何时放入一级缓存

    AbstractBeanFactory的doGetBean()方法中。运行createBean方法后,会调用getSingleton方法。

    // 创建bean的实例对象
    if (mbd.isSingleton()) {
        // 返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
        sharedInstance = getSingleton(beanName, () -> {
            try {
                // 为给定的合并后BeanDefinition(和参数)创建一个bean实例
                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.
                // 显示地从单例缓存中删除实例:它可能是由创建过程急切地放在那里,以允许循环引用解析。还要删除
                // 接收到该Bean临时引用的任何Bean
                // 销毁给定的bean。如果找到相应的一次性Bean实例,则委托给destoryBean
                destroySingleton(beanName);
                // 重新抛出ex
                throw ex;
            }
        });
        // 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
        // FactoryBean会直接返回beanInstance实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    这里的getSingleton方法和上面的不一样,如果从一级缓存没有找到,那么会调用addSingleton()方法将其加入到一级缓存中。

    	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    		// 如果beanName为null,抛出异常
    		Assert.notNull(beanName, "Bean name must not be null");
    		// 使用单例对象的高速缓存Map作为锁,保证线程同步
    		synchronized (this.singletonObjects) {
    			// 从单例对象的高速缓存Map中获取beanName对应的单例对象
    			Object singletonObject = this.singletonObjects.get(beanName);
    			// 如果单例对象获取不到
    			if (singletonObject == null) {
    				// 如果当前在destorySingletons中
    				if (this.singletonsCurrentlyInDestruction) {
    					throw new BeanCreationNotAllowedException(beanName,
    							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
    							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
    				}
    				// 如果当前日志级别时调试
    				if (logger.isDebugEnabled()) {
    					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
    				}
    				// 创建单例之前的回调,默认实现将单例注册为当前正在创建中
    				beforeSingletonCreation(beanName);
    				// 表示生成了新的单例对象的标记,默认为false,表示没有生成新的单例对象
    				boolean newSingleton = false;
    				// 有抑制异常记录标记,没有时为true,否则为false
    				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    				// 如果没有抑制异常记录
    				if (recordSuppressedExceptions) {
    					// 对抑制的异常列表进行实例化(LinkedHashSet)
    					this.suppressedExceptions = new LinkedHashSet<>();
    				}
    				try {
    					// 从单例工厂中获取对象
    					singletonObject = singletonFactory.getObject();
    					// 生成了新的单例对象的标记为true,表示生成了新的单例对象
    					newSingleton = true;
    				}
    				catch (IllegalStateException ex) {
    					// Has the singleton object implicitly appeared in the meantime ->
    					// if yes, proceed with it since the exception indicates that state.
    					// 同时,单例对象是否隐式出现 -> 如果是,请继续操作,因为异常表明该状态
    					// 尝试从单例对象的高速缓存Map中获取beanName的单例对象
    					singletonObject = this.singletonObjects.get(beanName);
    					// 如果获取失败,抛出异常
    					if (singletonObject == null) {
    						throw ex;
    					}
    				}
    				// 捕捉Bean创建异常
    				catch (BeanCreationException ex) {
    					// 如果没有抑制异常记录
    					if (recordSuppressedExceptions) {
    						// 遍历抑制的异常列表
    						for (Exception suppressedException : this.suppressedExceptions) {
    							// 将抑制的异常对象添加到 bean创建异常 中,这样做的,就是相当于 '因XXX异常导致了Bean创建异常‘ 的说法
    							ex.addRelatedCause(suppressedException);
    						}
    					}
    					// 抛出异常
    					throw ex;
    				}
    				finally {
    					// 如果没有抑制异常记录
    					if (recordSuppressedExceptions) {
    						// 将抑制的异常列表置为null,因为suppressedExceptions是对应单个bean的异常记录,置为null
    						// 可防止异常信息的混乱
    						this.suppressedExceptions = null;
    					}
    					// 创建单例后的回调,默认实现将单例标记为不在创建中
    					afterSingletonCreation(beanName);
    				}
    				// 生成了新的单例对象
    				if (newSingleton) {
    					// 将beanName和singletonObject的映射关系添加到该工厂的单例缓存中:
    					addSingleton(beanName, singletonObject);
    				}
    			}
    			// 返回该单例对象
    			return singletonObject;
    		}
    	}
    
    	/**
    	 * 将beanName和singletonObject的映射关系添加到该工厂的单例缓存中
    	 *
    	 * Add the given singleton object to the singleton cache of this factory.
    	 * 

    To be called for eager registration of singletons. * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // 将映射关系添加到单例对象的高速缓存(一级缓存)中 this.singletonObjects.put(beanName, singletonObject); // 移除beanName在单例工厂缓存中的数据(三级缓存) this.singletonFactories.remove(beanName); // 移除beanName在早期单例对象的高速缓存的数据(二级缓存) this.earlySingletonObjects.remove(beanName); // 将beanName添加到已注册的单例集中 this.registeredSingletons.add(beanName); } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
  • 相关阅读:
    902. 最大为 N 的数字组合 数位dp
    C++标准模板(STL)- 类型支持 (数值极限,round_style,is_iec559,is_bounded)
    如何优化并提供 Tomcat的启动速度
    【GoWeb项目-个人Blog】数据库表设计
    Python实时获取steam游戏数据
    14、Cahin of Responsibility 责任链 COR设计模式
    STM32WB55开发(6)----FUS更新
    阿里云服务器怎么退款?云服务器退款流程图
    【AGC】构建服务4-云数据库示例
    脏数据绕过waf,Yakit爆破base64编码密码,ssh无密码登录受害主机
  • 原文地址:https://blog.csdn.net/namelessmyth/article/details/133179360