2

私は Web 環境で Spring Framework 4.3.3 を使用しています。

私は2つのコンテキストを持っています:

  • RootApplicationContext
  • ServletApplicationContext

ServletApplicationContextたとえば、Web 側に関するすべての Bean が含まれていることはわかっています@Controller。さらに、たとえばなどServletApplicationContextからすべてのコンテキストまたは Bean にアクセスできます。ここまでは問題ありません。RootApplicationContext@Service, @Repository

@Configurationクラスにも適用されることに注意してください。(インフラストラクチャー)

したがって、前の紹介では、次のように考えることができます。

  • ServletApplicationContext-->RootApplicationContext

考慮すべき重要なことは、逆は不可能だということです。

したがって

  • RootApplicationContext-->ServletApplicationContext

できませ。センスがあってOKです。サーバー側は Web 側にアクセスすべきではありません

AspectJについて。私は次のものを持っています:

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {

}

ここで 1 つの重要なポイント:

  • これAopConfigはによってスキャンされますRootApplicationContext
    • のアクセスを通じてそれServletApplicationContextを参照できると信じています@ConfigurationRootApplicationContext

わかりました、@Testメソッドを実行すると。

私が使用するサーバー側から Test クラスを実行するとき

  • @ContextConfiguration(classes={RootApplicationContext.class} )
    • それだけRootApplicationContext

そして、AOPは正常に動作します。AOP + logging次のプロセスで確認できます。

  • @Service->@Repository

Web 側から Test クラスを実行するときは、次を使用します。

  • @ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
    • RootApplicationContext ServletApplicationContext

そして、AOPは正常に動作します。AOP + logging次のプロセスで 確認できます。

  • @Controller-> @Service->@Repository

今、生産のために私は持っています:

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootApplicationContext.class};
    }

   @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{ServletApplicationContext.class};
    }

しかし、プロジェクトを.warファイルにエクスポートし、URL/URI を介してController実行すると、期待される動作またはプロセスが正常に動作します。しかし、AOP についてAOP + loggingは、次のプロセスが発生します。

  • @Service->@Repository

@Controller出力には表示されません。予想されるフロー プロセスは次のようになります。

  • @Controller-> @Service->@Repository

では、なぜ本番環境ではなく、テスト環境で機能するのでしょうか?

私はすでに調査を行っており、次の2つの投稿を見つけました。

実際には、@Configurationクラスは@EnableAspectJAutoProxyスキャンする必要があり、スキャンする必要はないと言ってServletApplicationContextいますRootApplicationContext

それが正しい場合でも (新しい実験によると)、サーバー側は Web 環境なしでテストする必要があると考えてください。

その他のインフラストラクチャについては、すでに説明した関係@Beanを通じて、作品についてどのように期待されますか。AOPだけでこの状況があります。@ConfigurationServletApplicationContext --> RootApplicationContext

質問 01 : では、なぜこのような振る舞いをするのでしょうか?

質問 02AopConfig :スキャンを維持し、RootApplicationContext本番環境で期待される動作を取得するにはどうすればよいですか?

AopConfigによってスキャンされたかどうかに注意ServletApplicationContextしてください。テストに関する次のことは、サーバー側で有効かつ必須@ContextConfiguration(classes={RootApplicationContext.class, AopConfig.class} )です。の追加を参照しAopConfig.classAopConfigくださいRootApplicationContext

4

1 に答える 1

4

答えは@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})、テスト環境でのコンテキスト継承と本番環境でのコンテキスト継承は同じではないということです。テスト環境では、テスト アプリケーション コンテキストの一部としてRootApplicationContextおよびを含めます。ServletApplicationContext質問で説明したように、本番環境では、単純なインクルージョンの代わりに継承が使用されます。

BeanFactoryPostProcessor(あなたの場合は)親コンテキストから子@EnableAspectJAutoProxyコンテキストに適用されないようです。@EnableAspectJAutoProxy本番環境で機能させるには、子コンテキストでも明示的に定義する必要があります。

この場合、Spring コンテキスト定義は次のコードのようになります。

@Configuration
@Import(AopConfig.class)
public class RootApplicationContext {
    ...
}

@Configuration
@Import(AopConfig.class)
public class ServletApplicationContext {
    ...
}

または

@Configuration
@ComponentScan(basePackageClasses={AopConfig.Class, ...})
public class RootApplicationContext {
    ...
}

@Configuration
@ComponentScan(basePackageClasses={AopConfig.Class, ...})
public class ServletApplicationContext {
    ...
}

関連タスク

于 2016-09-26T05:32:22.537 に答える