一级缓存 存放成品bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
二级缓存 存放半成品bean
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
三级缓存 存放ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap
bean的创建流程
getBean->doGetBean-> createBean->doCreateBean->createBeanInstance->populateBean
场景:
有2个类,A类和B类
A类引用了B类
B类引用了A类,在spring创建两个类是如何解决循环依赖呢
循环创建A和B
- 循环到A
A类实例化doGetBean中getSingleton(beanName)获取不到A的bean继续往下执行
->A类实例化createBean
->A类实例化doCreateBean
->A类实例化createBeanInstance实例化,此时A的属性未被赋值,还未populateBean,属于半成品
->A类实例化doCreateBean中通过addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))放到三级缓存中,此时三级缓存中放的是lambda表达式
->A类实例属性赋值populateBean
->A类applyPropertyValues
->A类获取属性名称属性值,解析处理属性值(BeanDefinitionValueResolver.resolveValueIfNecessary方法),对对象属性进行赋值
->A类解析处理属性值b时,去调getBean方法创建B的bean
->B类实例化doGetBean中getSingleton(beanName)获取不到B的bean继续往下执行
->B类实例化createBean->B类实例化doCreateBean
->B类实例化createBeanInstance实例化,此时B的属性未被赋值,属于半成品
->B类实例化doCreateBean中通过addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))放到三级缓存中,此时三级缓存中放的是lambda表达式
->B类进行实例属性赋值populateBean
->B类applyPropertyValues
->B类获取属性名称属性值,解析处理属性值(BeanDefinitionValueResolver.resolveValueIfNecessary方法),对对象属性进行赋值
->B类解析处理属性值a时,去调getBean方法创建A的bean
->A类实例化doGetBean中getSingleton(beanName)方法中从三级缓存中拿到lambda表达式,执行函数式接口ObjectFactory的getObject方法的方法体(getEarlyBeanReference 方法),得到半成品的A,将A放到了二级缓存中(详见@1)
->B类获取到属性a的值后完成属性赋值
->B类doCreateBean方法中initializeBean方法进行bean的init操作(包括bean的afterProperties方法和initMethod等操作)
->B类doGetBean方法调用 getSingleton(beanName, new ObjectFactory<Object>()方法,将B的bean从三级缓存中移除放到了一级缓存中(详见@3)
->此时将B的值赋值给A类的属性b
->A类doGetBean方法调用 getSingleton(beanName, new ObjectFactory<Object>()方法,将A从二级缓存移除放到一级缓存中(详见@3),此时A为成品
2.循环到B
B类实例化doGetBean中getSingleton(beanName)获取到了B直接返回
@1:doGetBean中getSingleton方法 先从一级缓存拿beanObject,再从二级缓存拿,再从三级缓存拿,拿到为止(如果从三级缓存拿到了,会从三级缓存删除,并且添加到二级缓存中);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
//提前暴露对象
Object exposedObject = bean;
//如果bean需要被代理,在这里提前获取到代理类
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
@3 在这里(beanName, new ObjectFactory()方法中的addSingleton方法中将beanObject对象从二级或者三级缓存中取出放到一级缓存中
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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);
}
循环依赖可以被解决的原因:
1.populateBean之前的步骤可称之为实例化bean,populateBean之后的步骤称之为初始化bean,正是因为初始化和实例化是分开的,才可以解决循环依赖的问题。
2.提前暴露对象,将初始化完成的半成品bean放到三级缓存中,需要的时候执行三级缓存中的lambda表达式,将bean提前暴露出来
为什么需要三级缓存呢?
一级缓存: singletonObjects:用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
二级缓存: earlySingletonObjects:是为了处理循环依赖的对象创建问题,里面存的是半成品对象或半成品对象的代理对象
三级缓存: singletonFactories:单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖
三级缓存,用二级缓存能不能解决循环依赖?
通过ObjectFactory获取的Bean可能是两种类型,第一种就是实例化阶段创建出来的对象,还是一种就是实例化阶段创建出来的对象的代理对象。至于是不是代理对象,取决于你的配置,如果添加了事务注解又或是自定义aop切面,那就需要代理。这里你不用担心,如果这里获取的是代理对象,那么最后完全创建好的对象也是代理对象,ObjectFactory获取的对象和最终完全创建好的还是同一个,不是同一个肯定会报错,所以上面的理论依然符合,这里只是更加的细节化。
有了这个知识点之后,我们就来谈一下为什么要三级缓存。
第一级缓存,也就是缓存完全创建好的Bean的缓存,这个缓存肯定是需要的,因为单例的Bean只能创建一次,那么肯定需要第一级缓存存储这些对象,如果有需要,直接从第一级缓存返回。那么如果只能有二级缓存的话,就只能舍弃第二级或者第三级缓存。
假设除了二级缓存,没有三级缓存
二级缓存直接存储代理对象,而不是ObjectFactory
并不是说二级缓存如果存在aop的话就无法将代理对象注入的问题,本质应该说是初始spring是没有解决循环引用问题的,设计原则是: bean 实例化(通过反射实例化之后放到末级缓存中)、属性设置、初始化之后 再 生成aop对象(pring结合AOP跟Bean的生命周期本身就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来完成的,在这个后置处理的postProcessAfterInitialization方法中对初始化后的Bean完成AOP代理)
,如果二级缓存中直接存储代理对象,也就是说在 bean的实例的时候就要生成代理对象,然后再进行属性设置以及初始化和其他工作; 但是这样的话,就和spring的aop的设计原则相驳
二级缓存存储ObjectFactory
如果去掉了二级缓存,则需要直接在 singletonFactory.getObject() 阶段初始化完毕,并放到一级缓存中。
那有这么一种场景,B 和 C 都依赖了 A。A也依赖的B和C
->先创建A,实例化后存储到二级缓存,存储的是ObjectFactory的lambda表达式,
->给属性b赋值时去创建B,B又依赖了A,去二级缓存拿到ObjectFactory执行singletonFactory.getObject() 获取到A的代理对象。此时因为A不是成品,也不能将其代理对象放到一级缓存中,还得继续在二级缓存
->给属性c赋值时去创建C,C又依赖了A,去二级缓存拿到ObjectFactory执行singletonFactory.getObject() 获取到A的代理对象,此时会发现问题B和C获取到的A的代理对象不一样,因为singletonFactory.getObject()方法每次都返回一个新的代理对象
populateBean(beanName, mbd, instanceWrapper);//填充属性,会发生循环依赖 @1
exposedObject = initializeBean(beanName, exposedObject, mbd);//这里有后置处理器beanPostProcessor,可能会进行aop @2
当在实例化BeanA之后,会接着执行populateBean会填充beanB。结果beanB发现自己也需要依赖beanA,此时就会触发三级缓存中的ObjectFactory方法。如果beanA刚好要进行aop,那么在beanB的实例化过程中,由于beanB依赖了beanA,beanA就会提前进行aop。在@2处,进行aop之前会判断该beanName是否已经进行过aop,所以这个beanA不会再次被增强。
populateBean方法对Bean属性的依赖注入,BeanDefinitionValueResolver.resolveValueIfNecessary方法解析属性值
//解析属性值,对注入类型进行转换
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
//对引用类型的属性进行解析
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//调用引用类型属性的解析方法
return resolveReference(argName, ref);
}
//对属性值是引用容器中另一个Bean名称的解析
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
//从容器中获取指定名称的Bean
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
//对Bean类型属性的解析,主要是Bean中的内部类
else if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
//对集合数组类型的属性解析
else if (value instanceof ManagedArray) {
ManagedArray array = (ManagedArray) value;
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
//获取数组元素的类型
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
//使用反射机制创建指定类型的对象
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
//没有获取到数组的类型,也没有获取到数组元素的类型
//则直接设置数组的类型为Object
else {
elementType = Object.class;
}
}
//创建指定类型的数组
return resolveManagedArray(argName, (List<?>) value, elementType);
}
//解析list类型的属性值
else if (value instanceof ManagedList) {
return resolveManagedList(argName, (List<?>) value);
}
//解析set类型的属性值
else if (value instanceof ManagedSet) {
return resolveManagedSet(argName, (Set<?>) value);
}
//解析map类型的属性值
else if (value instanceof ManagedMap) {
return resolveManagedMap(argName, (Map<?, ?>) value);
}
//解析props类型的属性值,props其实就是key和value均为字符串的map
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
//创建一个拷贝,用于作为解析后的返回值
Properties copy = new Properties();
original.forEach((propKey, propValue) -> {
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
if (propKey == null || propValue == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting Properties key/value pair for " + argName + ": resolved to null");
}
copy.put(propKey, propValue);
});
return copy;
}
//解析字符串类型的属性值
else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
//获取属性的目标类型
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
//对目标类型的属性进行解析,递归调用
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
//没有获取到属性的目标对象,则按Object类型返回
else {
return valueObject;
}
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else if (value instanceof NullBean) {
return null;
}
else {
return evaluate(value);
}
}
//解析引用类型的属性值
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
//获取引用的Bean名称
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
//如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
bean = this.beanFactory.getParentBeanFactory().getBean(refName);
}
//从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化,则会递归触发引用Bean的初始化和依赖注入
else {
bean = this.beanFactory.getBean(refName);
//将当前实例化对象的依赖引用对象
this.beanFactory.registerDependentBean(refName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
BeanWrapperImpl对Bean属性的依赖注入
//实现属性依赖注入功能
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
if (tokens.keys != null) {
processKeyedProperty(tokens, pv);
}
else {
processLocalProperty(tokens, pv);
}
}
//实现属性依赖注入功能
@SuppressWarnings("unchecked")
private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
//调用属性的getter(readerMethod)方法,获取属性的值
Object propValue = getPropertyHoldingValue(tokens);
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
if (ph == null) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
}
Assert.state(tokens.keys != null, "No token keys");
String lastKey = tokens.keys[tokens.keys.length - 1];
//注入array类型的属性值
if (propValue.getClass().isArray()) {
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(lastKey);
Object oldValue = null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
requiredType, ph.nested(tokens.keys.length));
//获取集合类型属性的长度
int length = Array.getLength(propValue);
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
Class<?> componentType = propValue.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
setPropertyValue(tokens.actualName, newArray);
//调用属性的getter(readerMethod)方法,获取属性的值
propValue = getPropertyValue(tokens.actualName);
}
//将属性的值赋值给数组中的元素
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Invalid array index in property path '" + tokens.canonicalName + "'", ex);
}
}
//注入list类型的属性值
else if (propValue instanceof List) {
//获取list集合的类型
Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
List<Object> list = (List<Object>) propValue;
//获取list集合的size
int index = Integer.parseInt(lastKey);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
//获取list解析后的属性值
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
requiredType, ph.nested(tokens.keys.length));
int size = list.size();
//如果list的长度大于属性值的长度,则多余的元素赋值为null
if (index >= size && index < this.autoGrowCollectionLimit) {
for (int i = size; i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Cannot set element with index " + index + " in List of size " +
size + ", accessed using property path '" + tokens.canonicalName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
//将值添加到list中
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Invalid list index in property path '" + tokens.canonicalName + "'", ex);
}
}
}
//注入map类型的属性值
else if (propValue instanceof Map) {
//获取map集合key的类型
Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
//获取map集合value的类型
Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
Map<Object, Object> map = (Map<Object, Object>) propValue;
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
//解析map类型属性key值
Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor);
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
//解析map类型属性value值
Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
mapValueType, ph.nested(tokens.keys.length));
//将解析后的key和value值赋值给map集合属性
map.put(convertedMapKey, convertedMapValue);
}
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Property referenced in indexed property path '" + tokens.canonicalName +
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
}```