案例:A依赖B,B依赖A
1、A先实例化,同时把A放到三级缓存中,在初始化A对象里面的属性,发现有依赖B 2、创建实例B, 再把B放到三级缓存中,发现B又依赖A,执行属性填充也就是populateBean方法,里面会调用getSingleton方法Object sharedInstance = getSingleton(beanName);
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);
}
3、依次从存缓冲去获取A,其中一级、二级缓存中都没有,在从三级缓存中取,发现有,从三级缓存中取出,注意类型是ObjectFactory,然后调用getObject()方法
getObject实际调用的是getEarlyBeanReference方法
getEarlyBeanReference里面通过,拿到BeanPostProcess判断是否是SmartInstantiationAwareBeanPostProcessor类型,如果是调用getEarlyBeanReference方法
最终会吧beanName加到earlyProxyReferences里面,调用wrapIfNecessary方法,该方法会判断这个bean是否是被切面处理,如果不是返回原始实例的Bean
为什么要添加到earlyProxyReferences里面去?因为对于AOP在执行AnnotationAwareAspectJAutoProxyCreator的后置处理器的时候,也会创建代理对象,这里就是为了防止重复创建,
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);
//allowEarlyReference传的是false,不在从三级缓存中拿
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);
}
问题:
上面有个问题:
//1、先实例化AService exposedObject = initializeBean(beanName, exposedObject, mbd); //2、然后又从二级缓存中拿到了AService,在返回 Object earlySingletonReference = getSingleton(beanName, false);
既然二级缓存中已经有了,那么步骤1是不是有点多余了,其实不是的,我们先看
1、如果循环依赖都是普通的Bean首先,普通实例Bean和initializeBean方法返回的exposedObject是一个对象,包括二级缓存中拿到的earlySingletonReference都是一个地址
2、如果是AOP代理的Bean,那么二级缓存中拿到的Bean,是通过BService调用了AService的getEarlyBeanReference方法生成了代理Bean,为什么这么说,因为一开始实例化A的时候,已经吧AService的ObjectFactory存到了三级缓存中,而BService在处理依赖属性的时候,就调用了ObjectFactory的getEarlyBeanReference方法,来得到代理对象,最后由BService把A的代理对象Bean,存到了二级缓存中,所以在调用initializeBean方法,会返回代理对象,但是要注意,initializeBean创建代理对象走的是postProcessAfterInitialization方法,此时earlyProxyReferences里面是包含了AService,就不会在调用wrapIfNecessary方法。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
我们在看下ObjectFactory的getObject方法
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory
上面这2个方法都是通过wrapIfNecessary来创建代理对象,postProcessAfterInitialization创建代理对象是由AService调用initializeBean方法触发的,getEarlyBeanReference方法是BService在初始化内部属性时,调用AService的ObjectFactory.getObject()触发的,且BService顺序在initializeBean之前,所以先执行,同时把BeanName计入缓存earlyProxyReferences中,这个很重要,当initializeBean调用postProcessAfterInitialization创建代理Bean的时候,会先从缓存里面读,发现AService代理对象已经创建好了,就不会在创建了。所以无论如何AService也不会触发多次创建。(一定要理解这段话)
上图又有一个疑问:AService在实例化的时候,会调用populateBean完成属性填充,此时填充的是A的普通实例对象,B创建的AService实例对象是代理对象,最后返回的也是A的代理对象,我们后面调用都是用的代理对象,而A的代理对象也没有完成属性填充,populateBean填充属性填充的操作对象,是普通实例对象,是不是填充了寂寞?
解答:其实不是,在spring的AOP代理对象属性填充,填充的就是普通实例Bean,而且这个普通实例Bean我们是要用到的,创建AOP代理Bean时,是要传普通实例Bean
以JDK代理为例,执行目标方法时,还是通过我们上面创建的普通Bean,来调用的



