1、三级缓存
一级缓存(singletonObject)
:存储的是所有创建好了的单例Bean
二级缓存(earlySingletonObjects)
:完成实例化,但是还未进行属性注入及初始化的对象
三级缓存(singletonFactories)
:提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象
1.1、demo
package org.example.dependOn;
/**
* ---leetcode---
*
* @author summer77
* @date 2024/2/28 17:35
* <p>
* ---Demo1---
*/
public class Demo1 {
public Demo2 demo2;
public void setDemo2(Demo2 demo2) {
this.demo2 = demo2;
}
public Demo2 getDemo2() {
return demo2;
}
}
package org.example.dependOn;
/**
* ---leetcode---
*
* @author summer77
* @date 2024/2/28 17:35
* <p>
* ---Demo2---
*/
public class Demo2 {
public Demo1 demo1;
public Demo1 getDemo1() {
return demo1;
}
public void setDemo1(Demo1 demo1) {
this.demo1 = demo1;
}
}
package org.example.dependOn;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ---leetcode---
*
* @author summer77
* @date 2024/2/28 17:35
* <p>
* ---MyTest---
*/
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("a05.xml");
Demo1 demo1 = (Demo1) context.getBean("demo1");
Demo2 demo2 = (Demo2) context.getBean("demo2");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="demo1" class="org.example.dependOn.Demo1">
<property name="demo2" ref="demo2"/>
</bean>
<bean id="demo2" class="org.example.dependOn.Demo2">
<property name="demo1" ref="demo1"/>
</bean>
</beans>
1.2、源码剖析
- 直接看bean1创建时,在注入bean2前的处理
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 在这里完成了无参/有参构造
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
// 获取到完成构造的Bean,此时还未进行属性注入
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
// 关键在这里,如果当前Bean是单例且允许循环依赖且正在创建中
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
// 那么他需要早期暴露
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
// 我们看这里面
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// 属性注入阶段
this.populateBean(beanName, mbd, instanceWrapper);
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] 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 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
SmartInstantiationAwareBeanPostProcessor bp;
// 这个检查条件是不是很熟悉,AOP中见过,他的目的是检查这个bean是不是该被代理
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
for(Iterator var5 = this.getBeanPostProcessorCache().smartInstantiationAware.iterator(); var5.hasNext(); exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)) {
bp = (SmartInstantiationAwareBeanPostProcessor)var5.next();
}
}
// 如果不是动态代理Bean,那就直接返回原Bean了
// 如果是,需要先生成动态代理Bean
return exposedObject;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
// 一级缓存,存放完全创建好的Bean
// 确保Bean还没有进行属性注入
if (!this.singletonObjects.containsKey(beanName)) {
// 放入三级缓存
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
- 此时bean1放入了三级缓存,接着在
populateBean()
开始对Bean1的属性注入,然后一路追到解析引用的地方
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
// 获取Bean2的类类型
Class<?> beanType = ref.getBeanType();
Object bean;
// 判断这个Bean2是不是来自父工厂
// 如果来自父工厂就从父工厂中getBean()
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available");
}
if (beanType != null) {
bean = parent.getBean(beanType);
} else {
bean = parent.getBean(String.valueOf(this.doEvaluate(ref.getBeanName())));
}
} else {
// 不是父工厂的Bean
String resolvedName;
if (beanType != null) {
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
} else {
resolvedName = String.valueOf(this.doEvaluate(ref.getBeanName()));
// 进行bean2的getBean
bean = this.beanFactory.getBean(resolvedName);
}
this.beanFactory.registerDependentBean(resolvedName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
} catch (BeansException var7) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var7);
}
}
-
bean2此时还只是注册了BeanDefinition,三级缓存中都没有bean2,所以要进行bean2的初始化了,所以将进行bean2的createBean()
-
接下来的流程可以预料到,Bean2照常进行他的构造初始化,然后又被发现是个需要早期暴露的Bean,将其放入了三级缓存中
-
再然后bean2也进入了
populateBean()
方法中,他又要注入bean1,又回到了刚刚的方法。循环依赖产生了
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
// getBean("bean1")
bean = this.beanFactory.getBean(resolvedName);
}
- 又进入了对bean1的getBean(),因为有三级缓存的作用,这次会不太一样
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
Object sharedInstance = this.getSingleton(beanName);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存中拿已经完全创建好的bean1,现在自然是拿不到的 获取到的是NULL
Object singletonObject = this.singletonObjects.get(beanName);
// isSingletonCurrentlyInCreation 前面将bean1放入了这个表示bean正在创建的集合中
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
// 所以我们这次进入到了这里
// 此时二级缓存中也是没有bean1的,获取到的是NULL
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
//再次确认一级缓存中没有bean1
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//再次确认二级缓存中没有bean1
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 然后成功进入到了这里
// 这次是有的,在bean完成无参构造后检查到需要提前暴露,三级缓存放入了一个提前暴露的单例工厂,里面存放了bean1
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 获取到bean1
singletonObject = singletonFactory.getObject();
// 将bean1放入二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 移除三级缓存中的信息
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
// 最终返回了只进行了构造初始化的bean1
return singletonObject;
}
String beanName = this.transformedBeanName(name);
// 这次sharedInstance终于不为NULL了
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
//中间的代码题主跑了一通发现什么都没有发生,最终返回了bean1
return this.adaptBeanInstance(name, beanInstance, requiredType);
· 现在,bean2
拿到了还没完成属性注入的bean1
,我们回到resolveReference()
方法
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Class<?> beanType = ref.getBeanType();
Object bean;
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available");
}
if (beanType != null) {
bean = parent.getBean(beanType);
} else {
bean = parent.getBean(String.valueOf(this.doEvaluate(ref.getBeanName())));
}
} else {
String resolvedName;
if (beanType != null) {
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
} else {
resolvedName = String.valueOf(this.doEvaluate(ref.getBeanName()));
// 拿到了bean1
bean = this.beanFactory.getBean(resolvedName);
}
// 注册
this.beanFactory.registerDependentBean(resolvedName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
// 最终返回了bean1
return bean;
} catch (BeansException var7) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var7);
}
}
- 然后就是将bean1注入到bean2当中,bean2的属性注入就可以正常完成了,bean2被完整的创建了出来
- 然后再回到bean1的属性注入,bean1也获得了完全创建的bean2,此时bean1也可以正常的完成属性注入了,bean1也被完整的创建了出来
- 最后,二三级缓存的相关数据都会清掉,在一级缓存中放入完全创建好的Bean