上一篇文章进行了spring三级缓存在源码中使用的简要概括,因为没有实际类的举例,阅读起来有点绕。本篇博客是我自己在阅读spring源码过程中,对三级缓存是如何处理循环依赖问题的细节理解。一方面希望对你有所帮助,另一方面也是对自己阅读源码的一个完整的总结过程。话不多说,进入正题。
准备工作比较简单,准备两个类,然后类中相互引入作为对方的属性,在spring配置文件中注入,然后通过ClassPathXmlApplicationContext读取spring的配置文件。对应的源码如下:
1.1 创建两个类,User和Order
public class User {
private Order order;
public User() {
System.out.println("User无参构造,通过我创建对象了");
}
public User(Order order) {
this.order = order;
System.out.println("User全参构造,通过我创建对象了");
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
public class Order {
private User user;
public Order() {
System.out.println("Order类使用了无参构造函数,Order被创建了");
}
public Order(User user) {
this.user = user;
System.out.println("Order类使用了全参构造函数,Order被创建了");
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
1.2 spring配置文件applicationContext.xml中配置引用关系
1.3 创建main方法,读取spring配置文件
package com.edu.spring.study;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringStudyApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
}
准备工作有想这些就可以了,User和Order类相互引用,属于循环依赖,首先看下这样的相互引用能不能正常启动,执行main方法,得到如下效果:
可以看到没有报错,正常获取到bean对象,但是怎么处理这种情况?让相互依赖的两个类都正常创建,这是我们需要探究的问题。这里面其实就是使用了三级缓存来处理了。之前的文章对bean的创建过程有过梳理,这里就不再说明了。本文主要探索的是三级缓存在源码中的使用的探究。
当我们阅读到getSingleton(String beanName, ObjectFactory> singletonFactory)方法时,可以看到,对于一个已经创建好的对象,会将对象存入一级缓存中,存入一级缓存的逻辑在addSingleton()方法中,对于的源码如下:
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
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 (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
//得到一个bean对象
singletonObject = singletonFactory.getObject();
//将创建完成标识标记为true
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
//标记为已创建的对象,调用addSingleton()方法
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
继续查看addSingleton()的源码,源码如下:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
//将创建完成的bean存放到一级缓存singletonObjects中
this.singletonObjects.put(beanName, singletonObject);
//删除三级缓存中对应的bean信息
this.singletonFactories.remove(beanName);
//删除二级缓存中对应的bean信息
this.earlySingletonObjects.remove(beanName);
//将beanName存放到已创建bean的Set集合中
this.registeredSingletons.add(beanName);
}
}
对象保存二级缓存的逻辑在doGetBean方法中调用getSingleton(beanName)方法中实现的,跟踪源码最终的实现逻辑在getSingleton(String beanName, boolean allowEarlyReference)中,源码如下:
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//在一级缓存中查询bean对象
Object singletonObject = this.singletonObjects.get(beanName);
//判断bean是否为空,如果为空,校验bean是否正在创建中
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
//如果一级缓存中没有并且bean正在创建中,就在二级缓存中再次查询
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中如果查询不到的话,对一级缓存加锁
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
//再次查询一级缓存
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//一级缓存中如果bean不存在,查询二级缓存
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//二级缓存中查询不到的话,查询三级缓存
ObjectFactory> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//三级缓存中查询到的话,执行ObjectFactory的getObject()方法,该方法执行会调用createBean方法创建对象
singletonObject = singletonFactory.getObject();
//将创建的对象保存到二级缓存earlySingletonObjects的Map集合中
this.earlySingletonObjects.put(beanName, singletonObject);
//删除三级缓存中对应的bean信息
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
//返回获取的bean
return singletonObject;
}
从源码中可以看到,getSingleton()方法中会将bean信息存入二级缓存中。将bean对象放入二级缓存,就必须在三级缓存中存在bean信息,才可以得到bean对象,而三级缓存中存放的是以beanName作为key,ObjectFactory接口的实现类最为value的信息。那么接下来就需要找到三级缓存存放的位置。
前面我们已经看到了一级缓存和二级缓存的使用源码了,就是还没看到三级缓存的相关运用源码。接下来我们来探究三级缓存的源码,三级缓存的使用在doCreateBean()的方法逻辑中,源码如下:
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) {
//得到一个BeanWrapper类型的bean对象
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
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是否正在创建中,结果为true
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
//earlySingletonExposure的结果为true,进入if内部逻辑
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
//该方法中会将beanName作为Key,以lambda表达式:() -> {return this.getEarlyBeanReference(beanName, mbd, bean);}作为value
//保存到三级缓存中
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 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);
}
}
从上面的方法源码知道,在addSingletonFactory()方法中会将beanName相关信息保存到三级缓存中,是以beanName作为Key,以lambda表达式:() -> {return this.getEarlyBeanReference(beanName, mbd, bean);}作为value保存在三级缓存singletonFactories的Map集合中,下面我们看下这个addSingletonFactory()方法的源码,源码如下:
protected void addSingletonFactory(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//将以beanName作为key,ObjectFactory作为value,存放到三级缓存singletonFactories的Map集合中
this.singletonFactories.put(beanName, singletonFactory);
//删除二级缓存中对应的bean信息
this.earlySingletonObjects.remove(beanName);
//将beanName存放到已创建bean的Set集合中
this.registeredSingletons.add(beanName);
}
}
}
到此,spring源码中三级缓存的使用源码已经分析完成了,但是上面的源码只是一个三级缓存的使用代码,我们还是不知道具体如何解决的。这个我用文字描述,我自己感觉是说不清楚的我理解,我就用图示来表达一下我的个人的理解,理解不一定准确,也欢迎讨论。我的图示过程还是以User和Order类举例来说明。图示如下:
到这里,三级缓存的运用就全部总结结束了,到这里,spring的主流程也就梳理结束了。对我个人来讲,到这里spring的学习就告一段落了。spring的其他细节后续再研究了。。。