Springの“自動プロキシの対象外の原因を追跡する”

StackOverflow https://stackoverflow.com/questions/1201726

  •  05-07-2019
  •  | 
  •  

質問

Springの自動プロキシ機能をいじり始めると、文書化されているようにこの動作に遭遇することがよくあります:

  

を実装するクラス   BeanPostProcessorインターフェースは   特別なので、彼らは扱われます   コンテナによって異なります。すべて   BeanPostProcessorsとその直接   参照されるBeanはインスタンス化されます   起動時に、特別の一部として   の起動フェーズ   ApplicationContext、次にそれらすべて   BeanPostProcessorsが登録されます   ソートされた方法で-に適用されます   さらにすべての豆。 AOP以来   自動プロキシは次のように実装されます   BeanPostProcessor自体、いいえ   BeanPostProcessorsまたは直接   参照されるBeanは   自動プロキシ(したがって、   それらに「織り込まれた」側面。

     

このようなBeanについては、   情報ログメッセージ:“ Bean 'foo'はそうではありません   すべてによって処理される資格がある   BeanPostProcessors(例:not   自動プロキシの対象)”。

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

私の問題は、「直接参照」が「直接参照」であるため、その直接参照がどこにあるかを追跡するのは非常に難しいことです。実際、アプリケーションコンテキストでBeanの半分を取り込む推移的な依存関係のチェーンになります。 Springが提供するのはその単一の情報メッセージだけであり、Beanがこの参照のWebでキャッチされたときを知らせる以外に、それはあまり役に立ちません。

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

これを追跡するより良い方法を誰かが見つけましたか?

役に立ちましたか?

解決 2

この質問に何らかの閉鎖をもたらすために、初期化されていないオブジェクトグラフの崩壊は @Autowired を使用して BeanPostProcessor が依存関係を取得し、自動配線メカニズムによって引き起こされました。事実上、 BeanPostProcessor が問題について発言する機会を得る前に、他のすべてのBean定義が初期化されました。解決策は、BPPに自動配線を使用しないことです。

他のヒント

このレシピに従ってください:

  1. IDEで BeanPostProcessorChecker を開きます( AbstractApplicationContext の内部クラスです)
  2. メソッド postProcessAfterInitialization
  3. if(logger.isInfoEnabled()){にブレークポイントを設定します
  4. コードを実行
  5. ブレークポイントに到達したら、スタックトレースで getBean(String、Class< T>)の呼び出しを探します。

    これらの呼び出しの1つは、 BeanPostProcessor を作成しようとします。そのBeanが原因であるはずです。

背景

この状況を想像してください:

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

Springが config を作成する必要がある場合( FooPP の依存関係であるため)、問題があります:契約では、すべての BeanPostProcessor 作成されるすべてのBeanに適用する必要があります。ただし、Springが config を必要とする場合、サービスの準備ができていないPP(つまり FooPP )が少なくとも1つあります!

@Configuration クラスを使用してこのBeanを定義すると、これはさらに悪化します。

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

すべての構成クラスはBeanです。つまり、 BadSpringConfig からBeanファクトリを構築するには、Springはポストプロセッサ fooPP を適用する必要がありますが、そのためには、まずBeanファクトリが必要です...

この例では、循環依存関係の1つを解除することができます。 FooPP BeanFactoryAware を実装させ、Springに BeanFactory をポストプロセッサに注入させることができます。そうすれば、自動配線は必要ありません。

コードの後で、遅延してBeanを要求できます。

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(...);
}

LazyInitのソース

Beanファクトリとポストプロセッサ間のサイクルを中断するには、XML構成ファイルでポストプロセッサを構成する必要があります。 Springはそれを読み取り、混乱することなくすべての構造を構築できます。

助けになるかどうかはわかりませんが、Eclipse Spring IDE グラフビューは、Bean参照の整理に役立つようです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top