2009-07-29 9 views
35

の原因を追跡あなたは春の自動プロキシのものをいじり開始すると記載されているように、あなたは多くの場合、この動作に遭遇: BeanPostProcessorインタフェースを実装はSpringの「自動プロキシの対象ではない」

クラス が特殊なので、容器によって別様に処理されます。 すべての BeanPostProcessorsおよびその直接 参照豆は のApplicationContextの特別 起動フェーズの一部として、それらすべての BeanPostProcessorsがソートされた形で を登録され、起動時に をインスタンス化される - と にすべての更なる豆を適用。 AOP 自動プロキシが BeanPostProcessor自体として実装されているので、全く BeanPostProcessors直接 参照豆は 自動プロキシの対象としない(したがって 態様それらに「織」を持っていない。

任意ようについてBeanは、あなたが 情報ログメッセージが表示されます。「豆 『fooは』(例:自動プロキシの対象とならない )すべて BeanPostProcessorsによって処理されたばかりの対象とならない です」。

つまり、自分自身のBeanPostProcessorを作成し、そのクラスがコンテキスト内の他のBeanを直接参照している場合、それらの参照されるBeanは自動プロキシの対象にはならず、その旨のメッセージが記録されます。

私の問題は、「ダイレクトリファレンス」が実際にアプリケーションコンテキストで半分のBeanを取り込む過渡的な依存関係のチェーンになる可能性があるため、その直接参照がどこにあるかを追跡することが非常に難しいことです。すべてのSpringは、単一の情報メッセージであり、Beanがこの参照Webで捕捉されたことを知らせるだけではありません。

私が開発しているBeanPostProcessorは他のBeanへの直接参照を持っていますが、非常に限られた参照セットです。それにもかかわらず、ログメッセージによれば、コンテキスト内のすべてのBeanは自動プロキシから除外されていますが、その依存関係がどこで発生しているのかわかりません。

誰かがこれを追跡するより良い方法を見つけましたか?ただ、この質問には、いくつかの閉鎖をもたらすために

+0

また、 'PersistenceExceptionTranslator'クラスの情報メッセージを得ることができます。 – Raedwald

答えて

17

、崩壊初期化されていないオブジェクトグラフはBeanPostProcessorによって引き起こされ、その依存関係を取得するために@Autowiredを使用し、私のBeanPostProcessorが問題になる機会が得られる前に、autowireメカニズムが効果的に他のすべてのbean定義を初期化しました。解決策は、BPPにオートワイヤリングを使用しないことです。

+2

これは解決策ではありません。私のポストプロセッサに豆が必要なときに、私は何をするのですか? –

3

ない、それは任意のヘルプのだが、それは、Bean参照を整理に役立つことができようにEclipseのSpring IDEgraph viewが見えるかどうかわから..

21

このレシピフォロー:あなたのIDEで

  1. オープンBeanPostProcessorChecker
  2. はあなたのコードの実行方法postProcessAfterInitialization
  3. if (logger.isInfoEnabled()) {にブレークポイントを設定します(それがAbstractApplicationContextの内部クラスです)
  4. ときブレークポイントにヒットし、スタックトレースのgetBean(String,Class<T>)への呼び出しを探します。

    これらの呼び出しの1つは、BeanPostProcessorを作成しようとします。その豆は犯人でなければなりません。

背景

このような状況を想像して:

public class FooPP implements BeanPostProcessor { 
    @Autowire 
    private Config config; 
} 

春は(それがFooPPの依存性がありますので)configを作成する必要がある場合、それは問題があります。契約はすべてのことを言いますBeanPostProcessorは、作成されているすべてのBeanに適用する必要があります。しかし、Springにconfigが必要な場合、少なくとも1つのPP(つまりFooPP)がサービスの準備ができていません。あなたはこのBeanを定義するために@Configurationクラスを使用する場合

これはさらに悪化します:

@Configuration 
public class BadSpringConfig { 
    @Lazy @Bean public Config config() { return new Config(); } 
    @Lazy @Bean public FooPP fooPP() { return new FooPP(); } 
} 

すべてのコンフィギュレーションクラスがBeanです。それはBadSpringConfigから豆の工場を建設することを意味し、春にはポストプロセッサfooPPを適用する必要がありますが、それを行うためには、それが最初にこの例ではビーンファクトリ...

を必要とし、それは次のいずれかを破ることが可能です循環依存性。 FooPPBeanFactoryAwareを実装すると、BeanFactoryをSpringにポストプロセッサに注入させることができます。そうすれば、オートワイヤリングは必要ありません。

後のコードでは、あなたが怠惰豆を求めることができます:

private LazyInit<Config> helper = new LazyInit<Config>() { 

    @Override 
    protected InjectionHelper computeValue() { 
     return beanFactory.getBean(Config.class); 
    } 
}; 

@Override 
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
    String value = helper.get().getConfig(...); 
} 

source for LazyInit

をビーンファクトリポストプロセッサ間の悪循環を断ち切るために、あなたがポストを設定する必要がありますプロセッサをXML設定ファイルに格納します。 Springはそれを読んで、混乱することなくすべての構造を構築できます。

+0

このソリューションは、Webサービスのようなマルチスレッドアプリケーションに適していますか? – hudi

+0

'LazyInit'は安全です。そうです。 –

+0

私はJerseyアプリをSpring Bootに変換しているときに、この問題を追跡するためにこれを使用することができました。私は "conversionService"と呼ばれるBeanを持っていました.ConfigurationPropertiesBindingPostProcessorは、その名前の(オプションの)Beanを探します。 BeanPostProcessorでBeanを参照していたため、変換サービスで参照されているBeanが適切に配線されていなかった(@Autowiredフィールドが設定されていないなど)。 –

関連する問題