スプリングソースコード解析 - 周期依存性溶液

ウォッチメーターポケットJava.md

I.はじめに

着手「春のソース決意- Beanを作成する」を「春はソースコードを解析- Beanインスタンスを作成します」、そして、私たちは豆のObjectFactoryを作成する今日、循環依存のソリューションについて話しています。

二、のObjectFactory

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");
    }
    // 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
    /**
     * getEarlyBeanReference(beanName, mbd, bean)方法:
     * 对bean再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor
     * 其中我们熟知的AOP就是在这里将advice动态织入bean中,若没有则直接返回bean,不做任何处理
     */
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

このコードは非常に複雑ではありませんが、あまりにも多くの人々がこのコードの役割を理解し、それを理解するための機能からだけそのコードが意味を理解することは困難ではありません、私たちは、グローバルな視点から、Springの依存関係を考える必要がありますソリューション。
earlySingletonExposure:文字通りの意味から、一つのケースの早期露出を理解し、我々は条件がこの値に影響を与えるものに興味を持っているか、何の科学的な名前を定義しません。

  • mbd.isSingletonは():くらいこのRootBeanDefinitionが単一の場合を表しているかどうか、説明することができないがあります。
  • this.allowCircularReferencesは:循環依存関係を許可するかどうか、申し訳ありませんが、設定ファイルで設定する方法が見つかりませんでしたが、ハードコーディングであってもよいし、カスタム名前空間の構成、ここで提供される配置されたAbstractRefreshableApplicationContext機能を提供しています次のようにハードコーディングされたコードです。
ClassPathXmlApplicationContext bf = ClassPathXmlApplicationContext("aspectTest.xml" ); bt.setAllowBeanDefinitionOverriding(false);
  • isSingletonCurrentlylncreation(のbeanName):Beanが作成中です。春には、前者はのbeanNameは、Beanで、Beanの終了後にプロパティから削除されます作成し、プロパティに記録されているのbeanNameの作成を開始します、豆を記録するためにsingletonsCurrentlylnCreationの特別な属性のデフォルトの負荷状態DefaultSingletonBeanRegistryがあるでしょう。その後、我々は道に沿って、レコードのコードに従うが、このプロパティはあまり印象を持っていなかった、これはレコードがそれ状態ですか?異なるスコープの記録位置が同じではない、我々は、シングルトン、例えば、シングルトンプロパティに記録された関数は、(文字列のbeanName、のObjectFactory singletonFactory)beforeSingletonCreation関数(のbeanName)のDefaultSingletonBeanRegistryとafterSingletonCreation(のbeanName)で公共オブジェクトgetSingletonであり、これら二つの機能は、除去の状態を記録するためのthis.singletonCurrentlylnCreation.add(のbeanName)とthis.singletonCurrentlylnCreation.remove(のbeanName)です。

上記の分析後、循環依存を許可するかどうか、我々は単一可変アールearlySingletonExposure例であるかどうか、対応するBeanが作成されるかどうかの一般的な用語を理解します。これらの三つの条件が満たされたときaddSingletonFactoryは、操作を実行する場合、どのような役割は、それがSingletonFactoryに参加するのですか?そして、何時にそれを呼び出すには?

以下に示すように、クラスBは、その後、初期化プロセスbeanAを属性クラスAが含まれていますしながら、私たちの最も簡単なケース循環依存関係はAB、クラスAクラスBは、属性を含みます:
beanA.md

上图展示了创建 beanA 的流程,图中我们看到,在创建 A 的时候首先会记录类 A 所对应的 beanName,并将beanA的创建工厂加入缓存中,而在对 A的属性填充也就是调用populate方法的时候又会再一次的对 B 进行递归创建。同样的,因为在 B 中同样存在 A 属性,因此在实例化 B 的的 populate 方法中又会再次地初始化 A ,也就是图形的最后,调用 getBean(A)。关键是在这里,有心的同学可以去找找这个代码的实现方式,我们之前已经讲过,在这个函数中并不是直接去实例化 A ,而是先去检测缓存中是否有已经创建好的对应的 bean ,或者是否已经创建好的 ObjectFactory,而此时对于A的 ObjectFactory我们早已经创建,所以便不会再去向后执行,而是直接调用 ObjectFactory去创建 A 。这里最关键的是 ObjectFactory的实现。

/**
 * getEarlyBeanReference(beanName, mbd, bean)方法:
 * 对bean再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor
 * 其中我们熟知的AOP就是在这里将advice动态织入bean中,若没有则直接返回bean,不做任何处理
 */
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

其中getEarlyBeanReference的代码如下:

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;
}

在 getEarlyBeanReference 函数中并没有太多的逻辑处理,或者说除了后处理器的调用外没有别的处理工作,根据以上分析,基本可以理清 spring 处理循环依赖的解决办法,在 B 中创建依赖 A 时通过 ObjectFactory 提供的实例化方法来中断 A 中的属性填充,使 B 中持有的 A 仅仅是刚刚初始化并没有填充任何属性的 A ,而这正初始化 A 的步骤还是在最开始创建 A 的时候进行的,但是因为 A 与 B 中的 A 所表示的属性地址是一样的,所以在 A 中创建好的属性填充自然可以通过 B 中的 A 获取,这样就解决了循环依赖的问题。

三、小结

大体上的原理就是这样,有什么不明白的地方,大伙可继续阅读如下文章:

https://blog.csdn.net/m0_38043362/article/details/80284577

https://blog.csdn.net/hzcao/article/details/78479593

http://book.51cto.com/art/201311/419098.htm

公共ポケット米へのリンクの数に基づいて、

https://mp.weixin.qq.com/s/P7f0HLnyjHqoN4-rUm0ytQ

ようこそ懸念メートルポケットJavaは、ノートに共有し、交流学習のJavaプラットフォームに。

ライスポケットJava.md

おすすめ

転載: www.cnblogs.com/midoujava/p/11291487.html