// 如果两个条件满足,说明出现了循环依赖
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 再从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
// 这里又有两个判断
// singletonObject == null 表示在二级缓存中没有获取到
// allowEarlyReference 这个值传进来就为true,表示是否允许获取早期引用
// 如果两个条件都满足,就到三级缓存中获取
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存获取,注意,这里获取到是一个ObjectFactory
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过ObjectFactory获取bean实例
singletonObject = singletonFactory.getObject();
// 打怪升级,从三级缓存升级到二级缓存,
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
// 返回bean
return singletonObject;
}
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, “Bean name must not 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 be null”);
synchronized (this.singletonObjects) {
// 从一级缓存中获取bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果bean为空
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 (logger.isDebugEnabled()) {
logger.debug(“Creating shared instance of singleton bean '” + beanName + “'”);
}
// 单例bean创建前会将这个bean放到一个容器中,标志这个bean正在创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 执行匿名内部类方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 单例bean创建完成后,会把bean从这个容器中移除
afterSingletonCreation(beanName);
}
// newSingleton为true时,表示bean创建成功
if (newSingleton) {
// 把bean放到一级缓存中,一级缓存就是我们常说的IOC容器
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 放进一级缓存中
this.singletonObjects.put(beanName, singletonObject);
// 从三级缓存中移除
this.singletonFactories.remove(beanName);
// 从二级缓存中移除
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
从上面的代码我们已经可以总结出bean没有出现循环依赖时,流程是怎么样的?
-
getSingleton()方法查看是否存在于一级缓存中,是则获取,无则走下面的创建流程,因为没有出现循环依赖,isSingletonCurrentlyInCreation(beanName),此判断是false
-
createBean()方法创建一个bean
-
addSingleton()方法将bean放到一级缓存中
当然,在正常的流程中会穿插异常流程的处理方式,比如bean创建前会把bean放到一个容器中,Spring凭借这个可以知道bean是否正在创建中,得知bean在创建中后,会利用三级缓存获得bean空壳
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
…
// mbd.isSingleton():bean是否是单例
// this.allowCircularReferences:是否允许出现循环依赖
// isSingletonCurrentlyInCreation(beanName):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放到三级缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// bean初始化
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);
}
}
// 如果出现了循环依赖
if (earlySingletonExposure) {
// 从各级缓存中获取bean,getSingleton(beanName, false)这个方法是不是很熟悉,上面已经使用到了
// 只是第二个参数从true变成了false,这个参数决定了要不要从第三级缓存中获取数据
// 代码走到这个地方,已经无需获取早期引用了,所以参数为false
Object earlySingletonReference = getSingleton(beanName, false);
// 如果二级缓存不为空
if (earlySingletonReference != null) {
// 并且二级缓存中的bean跟exposedObject相等,说明初始化时,没有使用代理修改bean对象
if (exposedObject == bean) {
// 直接将二级缓存中bean返回即可
exposedObject = earlySingletonReference;
}
…
return exposedObject;
}
我们重点看看addSingletonFactory()这个方法,我们先看一段简单代码,感受一下ObjectFactory这个类的作用
public class ObjectFactoryTest {
public static void main(String[] args) {
HashMap
map.put(“a”, () -> {
System.out.println(“objectFactory”);
return “string”;
});
System.out.println(map.get(“a”).getObject());
}
}
原来,ObjectFactory可以定制执行方法,那么Spring要定制的执行方法是什么?
protected void addSingletonFactory(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(singletonFactory, “Singleton factory must not be null”);
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 放入三级缓存
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
// 要定制的执行方法就是一个beanPostProcess的埋点
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
// AOP的beanPostProcess重写了这个方法
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
原来,要定制执行方法的原因是,bean的初始化的过程中,AOP动态代理有可能对这个bean进行增强,增强后的bean就是一个代理类,不是原来的类,循环依赖时,我们要提前暴露bean,但是动态代理的过程也要走,鱼和熊掌都要,就使用了这种比较骚气的方式
从上面的代码中,我们可以总结出出现循环依赖时,流程是怎么样的?
-
addSingletonFactory()方法会将实例化好的空壳对象放在三级缓存中
-
getSingleton()方法查看到出现循环依赖,会从三级缓存中获取bean,执行定制方法,如果是简单对象,则将简单对象放进二级缓存中,如果是动态代理对象,则将动态代理对象放进二级缓存中
-
bean生命周期走完后,会把bean放进一级缓存中
测试一下
====
@Controller
public class A {
@Autowired
private B b;
public void test(){
System.out.println(“a”);
}
}
@Controller
public class B {
@Autowired
private A a;
public void test(){
System.out.println(“b”);
}
}
定义一个切面,如果有这个测试类,可以看到调用动态代理方法的过程
@Aspect
@Component
public class AspectDemo {
@Pointcut(“execution(* *.test(…))”)
public void test(){}



