9

Spring 3 AOPを使用していますが、HttpServletRequestへのアクセスが必要な側面があります。これは次のようになります。

@Aspect
public class MyAspect {

    @Autowired
    private HttpServletRequest httpServletRequest;

    public void init() {
        // Do something once...
    }

    @Before("my pointcut here...")
    private void myMethod() {
        // I need the httpServletRequest...
    }

    @After("my pointcut here...")
    private void myOtherMethod() {
        // I need the httpServletRequest...
    }
}

そして、次のように構成されます。

<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" />

これはアスペクトであり、httpServletRequestスレッドは安全ですが、initメソッドはIoCコンテナごとに1回だけ呼び出されますか?そうでない場合は、アドバイスの実行中にそれを取得し、スレッドセーフにするための最良の方法は何ですか?可能であれば、ローカルスレッドを使用しないことをお勧めします。

4

1 に答える 1

18

initメソッドはIoCコンテナごとに1回だけ呼び出されますか

Beanインスタンスごとに1回呼び出されます。Beanにシングルトンスコープがある場合(これはアスペクトのデフォルトの場合でもあります)、呼び出されるのは1回だけです。httpServletRequestただし、 insideメソッドにアクセスすることはできませんinit()-まだリクエストはありません!

httpServletRequestスレッドセーフです

そうではありませんが、心配しないでください。これは実際には見た目よりもはるかに複雑です。シングルトンオブジェクトにHTTPサーブレットリクエストを挿入しています(そして明らかに同時に複数のリクエストが利用可能である可能性があります)。どちらが注入されますか?それらのどれも(すべて?)!Springはいくつかの洗練されたプロキシ(スコーププロキシと呼ばれる)を作成し、注入されたメソッドにアクセスするたびに、それらを現在の(スレッドへの)要求httpServletRequestに委任します。このようにして、アスペクトを複数のスレッドで安全に実行できます。それぞれが異なる物理リクエストで動作します。

この動作全体は、4.5.4.5スコープ付きBeanに依存関係として詳細に説明されています。

[...] (たとえば)HTTPリクエストスコープのBeanを別のBeanに注入する場合は、スコープのBeanの代わりにAOPプロキシを注入する必要があります。つまり、スコープオブジェクトと同じパブリックインターフェイスを公開するが、関連するスコープから実際のターゲットオブジェクト(HTTPリクエストなど)を取得し、メソッド呼び出しを実際のオブジェクトに委任できるプロキシオブジェクトを挿入する必要があります。 。

についてThreadLocal

私はローカルスレッドを使用したくない。

幸いなことに、Springはあなたのために1つを使用しています。仕組みを理解している場合ThreadLocal-プロキシにアクセスすると、Springは現在のリクエストをスレッドローカルに入れ、スレッドローカルインスタンスに委任しますhttpServletRequest

于 2012-05-10T20:56:17.530 に答える