これは、
4番目のポストプロセッサのソースコードスタディノートです。4番目のポストプロセッサは、主に循環依存をサポートするためのものです。
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
これは、4番目のポストプロセッサのメソッド名です。春のソースコードでは、このメソッドを実装するbeanPostProcessorは2つだけです。それらは次のとおりです。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#getEarlyBeanReference
その中で、InstantiationAwareBeanPostProcessorAdapterのgetEarlyBeanReference()メソッドは何もしませんが、Beanをそのまま返します。
主な関数はAbstractAutoProxyCreator#getEarlyBeanReferenceにあります。
まず、このメソッドのコードを見てみましょう。
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
return wrapIfNecessary(bean, beanName, cacheKey);
}
コードは数行しかありませんが、これらのコード行は実際には8番目のポストプロセッサ(動的プロキシオブジェクトの生成)が実行するものであることがわかります。
次に、4番目のポストプロセッサの外層のロジックを見てみましょう。
/**
* 第四个后置处理器执行的前提条件是:
* 1.当前bean是单实例的
* 2.当前beanFactory允许循环依赖:allowCircularReferences这个参数没找到在哪个扩展点中可以改为false,初始化默认是true,所以我们姑且认为大部分情况下这个参数都是true
* 3.当前bean正在创建中,这里是判断是否在一个集合中
* singletonsCurrentlyInCreation会在开始初始化之前,判断当前bean是单实例的时候,加入到集合中
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
/**
* mpy 第四次调用后置处理器 获取一个提前暴露的对象 objectFactory 用来解决循环依赖
* 这里还有一个关键的作用,可以追进去看一下,这里可能会完成动态代理对象的生成(AOP)
* 正常情况下,AOP的动态代理是在调用org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)的时候,才会生成(也即:第八个后置处理器)
* 但是,如果是循环依赖的话,会在 org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference(java.lang.Object, java.lang.String) 中完成
*
* 所以:对于循环依赖,这里提前暴露的对象,虽然没有完成后面的初始化方法的解析(invokeInitMethod),但是完成了动态代理对象的生成
*
* 这里getEarlyBeanReference();不会立即执行,而是在从二级缓存中获取对象的时候,会调用该方法,在该方法中完成动态代理
*
*/
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
/**
* 这里是第四个后置处理器的逻辑
* 在这里,会把第四个后置处理器作为一个ObjectFactory存入到一个map集合中
* 所以这个后置处理器,并不会立即执行,而是在从map取出来的时候,会被执行,那什么时候会被取出来呢?
* 在循环依赖中
* Add the given singleton factory for building the specified singleton
* if necessary.
* <p>To be called for eager registration of singletons, e.g. to be able to
* resolve circular references.
* @param beanName the name of the bean
* @param singletonFactory the factory for the singleton object
*/
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
/**
* 这里会加一层判断,如果单实例池中已经有bean对象了,就无须再插入到singletonFactories中,此时也就不存在
* 循环依赖的问题了
*/
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
ここでのロジックは、主に属性の循環依存関係のためのこれらの数行のコードです。4番目のポストプロセッサはいつ呼び出されますか?
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
/**
*
* singletonObjects是spring单实例池
* 我们暂时称
* earlySingletonObjects为三级缓存 该map是在后面进行判断,是否允许循环依赖,如果允许,就把bean存到这个map中
* singletonFactories为二级缓存 在判断是单实例bean的时候,将包含bean的beanFactory存到该map中,这个map中存储的是一个生成代理对象的factory
* singletonObjects为一级缓存,存储的是实例化之后的bean
*
* 在这里,三级缓存的map保存的是从二级缓存中取到的一个对象,取到之后,从二级缓存中将bean删除
* 这样做是为了防止重复创建,
*
* 在获取到依赖的对象之后,会进行一次类型校验 org.springframework.beans.factory.support.AbstractBeanFactory#isTypeMatch(java.lang.String, org.springframework.core.ResolvableType)
*
* 循环依赖的处理:
* 如果A注入了B,B也注入了A;在第一次实例化A的时候,会注入A,注入A的时候,会反过来去实例化B
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//mpy 这里只需要从二级缓存中拿一次就行,如果没有二级缓存,每次进来都需要从二级缓存get一次,影响效率
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
/**
* 这里getObject会调用getEarlyBeanReference(beanName, mbd, bean)方法,完成动态代理对象的生成
* 这里为什么要调用这个方法?
* 我的理解是这样的:在属性注入之后,还有两个后置处理器需要调用:
* 1.applyBeanPostProcessorsBeforeInitialization invokeInitMethod方法,也即:调用bean的初始化方法的后置处理器
* 2.applyBeanPostProcessorsAfterInitialization 这里完成的是:代理对象的生成(比如:AOP动态代理对象生成,事务方法代理对象生成)
*
* 既然有了循环依赖,总要有一个bean是要先注入的,在注入
*/
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
以上で、4番目のポストプロセッサは循環依存関係の処理を完了することです
。AがBに依存し、BがAに依存する場合、最初にAオブジェクトの動的プロキシオブジェクトの生成を完了し、次に注入後に、次に、属性インジェクション、初期化メソッドコールバック、およびその他のメソッドを実行します。実際、私が理解していない点が1つあります。循環依存関係では、Beanをインジェクトするときに最初に動的プロキシオブジェクトの生成を完了する必要があるのはなぜですか。