記事のディレクトリ
この章では、我々は、主の話を
doCreateBean()
`春には、円形の依存関係を解決することであり、いくつかは間違った方法を使用する方法、プロセス。
問題
我々は二つのクラス、すなわち、持っていることを今仮定しA
、クラス、B
クラス、およびA
を参照するクラスの必要性B
クラス、B
を参照するクラス必要A
ベビーモードの集合であるクラスを、。
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
だから、春には、この状況をどう処理しますか?
ここでは、Beanのバネ付きプロセスを再訪しました。
ソリューション
実際には、ロード・プロセス・ソリューションの前に限り、非常に単純であるから填充Bean属性
、直接に間にBeanFactory
できるのでバック電流依存豆に続いたBeanFactoryから直接取得することができ、することは外出に戻り、作成には行きません豆のプロセス。
ここでは、豆の視点で見て解決する方法です。
これは死のサイクルが作成されているから飛び出しました。
非通常のパフォーマンス
彼らはそれが安全であると思うかどうかを上記の解決策を読みますか?あなたは大胆な循環依存豆を安心することができますか?
ここでは例を見て、それが上記の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.");
}
}
}
}
あるいは、一歩一歩を行きます
- 元ビーンたBeanFactoryを介して取得する最初のステップ
- 第二段階、豆と豆は同じの作成かどうかを判断するために、検索(重要なのは...何人かの学生はまだ上で打つ?)、ビーンが作成したダイレクトリターンと同じ
- 内部電流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(){}
}