web-dev-qa-db-ja.com

スプリング自動配線AOP循環依存

私はJava config with _@ComponentScan_ inを使用して、Beanと@EnableAspectJAutoProxy(proxyTargetClass=true)を初期化してcglibプロキシを使用しています。

このプロジェクトでは、_@Autowired_を使用して生成された多くのサービスがそれらの間で自動接続されています。かなりうまくいきます。

しかし、これらのサービスの一部については、_@Async_を追加しました(_@Configuration_ classにも@EnableAsync(proxyTargetClass = true)を追加しました)。

その後、私は得ています:

_Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ConversationUserLocalService': Bean with name 'ConversationUserLocalService' has been injected into other beans [ConversationUserHistoryLocalService] i
n 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 'a
llowEagerInit' flag turned off, for example.
_

これは、AOPがプロキシを作成する前に、Springが_@Async_ methodでサービスを注入しているためだと思います。これが問題なのでしょうか?どうすれば修正できますか?

私の問題を明確にするために、私が持っているとしましょう:

@サービスA、B、C

Aに自動配線されたBおよびC Bに自動配線されたAおよびC Cに自動配線されたAおよびBがある

Cには@Asyncとしてマークされたメソッドがあります。

SpringがapplicationContextを初期化するとき、Aを初期化しようとしますが、BとCが必要なので、それらを初期化します。しかし、結局のところ、AOPは(@Asyncが原因で)Cのプロキシを作成しようとし、BとAに自動配線されたCがCのプロキシと同じではないことを検出し、失敗します。

これで何が起こっているかをもう少し説明できるといいのですが。

24
ilopezluna

AsyncConfigurer構成クラスは、アプリケーションコンテキストブートストラップの初期段階で初期化されます。そこで他のBeanに依存関係が必要な場合は、それらを他のポストプロセッサも通過させるために、可能な限り「遅延」と宣言するようにしてください。

参照JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html

0
masT

最後に、@Lazyonサービス(@Asyncアノテーションが付いたメソッド)、およびを使用して、自動配線された場所で分類しました。このように、Springは、アプリケーションコンテキストの初期化ではなく、必要な場合にのみそれらのサービスを初期化し、自動配線します。

34
ilopezluna

@Autowireと一緒に@Qualifierを追加することで、同様の問題を修正することができました。例えば:

@Autowired
@Qualifier("publisher")
private Publisher publisher;
0
Joel Mata