[春]の研究ノート7つの循環依存関係ソリューション


この章では、我々は、主の話を doCreateBean() `春には、円形の依存関係を解決することであり、いくつかは間違った方法を使用する方法、プロセス。

問題

我々は二つのクラス、すなわち、持っていることを今仮定しA、クラス、Bクラス、およびAを参照するクラスの必要性Bクラス、Bを参照するクラス必要Aベビーモードの集合であるクラスを、。

@Component
public class A {
  @Autowired
  private B b;
}

@Component
public class B {
  @Autowired
  private A a;
}

だから、春には、この状況をどう処理しますか?
ここでは、Beanのバネ付きプロセスを再訪しました。

存在
不存在
在BeanFactory中获取Bean
是否存在Bean
返回Bean
创建Bean

ソリューション

実際には、ロード・プロセス・ソリューションの前に限り、非常に単純であるから填充Bean属性、直接に間にBeanFactoryできるのでバック電流依存豆に続いたBeanFactoryから直接取得することができ、することは外出に戻り、作成には行きません豆のプロセス。

ここでは、豆の視点で見て解決する方法です。

创建A实例
将A实例添加到BeanFactory
填充A属性触发创建B实例
创建B实例
填充B属性触发创建A实例
在BeanFactory中获取到A实例

これは死のサイクルが作成されているから飛び出しました。

非通常のパフォーマンス

彼らはそれが安全であると思うかどうかを上記の解決策を読みますか?あなたは大胆な循環依存豆を安心することができますか?

ここでは例を見て、それが上記の2つのカテゴリにのみいくつかの小さな変化に基づいています。

@Component
public class A {
  @Autowired
  private B b;
  @Async
  public void async(){}
}

@Component
public class B {
  @Autowired
  private A a;
  @Async
  public void async(){}
}

私たちは、注釈を追加するだけの方法だ@Async、その後、状況は劇的に変化します。

与えられています
その後、循環依存関係を考慮すると、前記豆warpperを用います。

良いが、円形の依存関係の事を解決されていることを言うことではありませんか?どのようにこのエラーを報告しましたか?

この@Asyncエンドでの注釈は悪魔ものです。

私たちは、最初に投げ出され、最終的に間違っているこの場所を見てみましょう。

ビーンが作成した後に次のコードが発生します。

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

あるいは、一歩一歩を行きます

  1. 元ビーンたBeanFactoryを介して取得する最初のステップ
  2. 第二段階、豆と豆は同じの作成かどうかを判断するために、検索(重要なのは...何人かの学生はまだ上で打つ?)、ビーンが作成したダイレクトリターンと同じ
  3. 内部電流wrappingBeanとBeanの依存性が注入させ、依存性が使用された場合に第3のステップは、それが上記のエラーをスローします。

一般的なケースならば、我々が作成したオリジナルの豆と豆がまったく同じであるため、我々は、第二段階での復帰を指示します。(すなわち、NO @Asyncアイデアが事を思いついたときにコメント?)

私は、順番に、使用し、その後、思った@Async豆を作成するために私たちを導くとからなり、注釈をBeanFactory元ビーンを見るには矛盾。

なぜ?

最初の@Async注釈機能は侵入せず、それを達成するためにどのようにして、非同期操作の同期動作を変換するのですか?右の演技。そう、プロキシクラスを作成するための豆が返されます。それは同じではありません。

だから、長い豆をプロキシすることができ、注釈として、それはこの問題が発生します。(循環依存)

ソリューション

それでは、どのようにそれを解決するには?

@Lazy春があるため注意、@Lazy条件を決定するには、到達したと検出をスキップすることはできません。

else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) 

つまり、this.allowRawInjectionDespiteWrapping値がtrueになります。

ので@Lazyノートがプロキシビーン返されるので、この春の豆は、このテストをスキップしてみましょう。

例:

@Component
public class A {

  @Autowired
  @Lazy
  private B b;

  @Async
  public void async(){}

}

@Component
public class B {

  @Autowired
  @Lazy
  private A a;

  @Async
  public void async(){}

}
リリース9件のオリジナルの記事 ウォンの賞賛0 ビュー119

おすすめ

転載: blog.csdn.net/qq_18300037/article/details/104076902