2

サービスのすべてのパブリックメソッドにアスペクトラッパーがあり、エンティティをコントローラーに返す前にデータベースからデタッチするとします。

@Around("execution(public * *(..)) && @within(org.springframework.stereotype.Service)")

あるサービスが別のサービスを直接呼び出している場合、このラッパーもトリガーされます。例えば:

@Service
class ServiceA {
    @Autowired
    ServiceB b;

    public void foo() {
        b.bar();
    }
}

@Service
class ServiceB {
    public void bar() {
    }
}

を呼び出すServiceA.foo()と、ラッパーはへのネストされた呼び出しの周りにもトリガーさbar()れます。

への呼び出しの前後でトリガーする必要がありますがfoo()、ではありませんbar()。どうすればこれを回避できますか?

4

2 に答える 2

1

私は時々、ThreadLocal変数を使用してこの種の問題を解決しました。次のようなものを試してください:

@Aspect
public class DetacherAspect {

    private final ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();

    @Around("execution(public * *(..)) && @within(org.springframework.stereotype.Service)")
    public Object execute(ProceedingJoinPoint pjp) throws Throwable {

        boolean isNested = threadLocal.get() != null;
        if (!isNested) {
            // Set some object (better create your own class) if this is the first service
            threadLocal.set(new Object());
        }

        try {


            ... // Your aspect


        } finally {

            // Clean thread local variables
            if (!isNested) {
                threadLocal.remove();
            }

        }

    }

}

明らかに、これはすべての呼び出しが同じスレッドで行われる場合にのみ機能します。スレッドローカル変数には他にもいくつかの欠点があり、それらについて読むのは良いことです。

于 2012-09-05T13:21:36.270 に答える
0

私はiPadだけを持って出かけているので、今はテストできませんが、次のように試してみることができます。

pointcut myCalls() :
    execution(public * *(..)) && @within(org.springframework.stereotype.Service);
pointcut myCallsNonRecursive() :
    myCalls() && !cflowbelow(myCalls())

around() : myCallsNonRecursive() {
    // ...
}

AspectJのネイティブ構文については申し訳ありませんが、私はそれをよく知っています。

于 2012-09-05T17:38:47.597 に答える