1

同じ JVM (Glassfish ドメインなど)で実行されているすべてのアプリケーションで、javax.persistence.EntityManager.flush() と言うすべての呼び出しをインターセプトできるかどうか疑問に思っています。

以下はまだ役に立たない;-(

@Aspect
public class TraceAspect {

    @Pointcut("within(@(@javax.persistence.PersistenceContext *) *)")
    public void entityManagers() {
    }

    @Pointcut("execution(@javax.persistence.EntityManager *.merge) && args(object)")
    public void merge(Object o) {
    }

    @Pointcut("execution(@javax.persistence.EntityManager *.createQuery) && args(string)")
    public void createQuery(String s) {
    }

    @AfterReturning("entityManagers() && merge(object)")
    public void afterMerge(JoinPoint joinPoint) {
        System.out.println(joinPoint);
    }

    @AfterReturning("entityManagers() && createQuery(string)")
    public void afterCreateQuery(JoinPoint joinPoint) {
        System.out.println(joinPoint);
    }
}
4

1 に答える 1

1

アプリケーションサーバー/コンテナについてはほとんど知りませんが、基本的にはクラスローディングの問題であるはずです。インターセプトされるクラスが論理アプリ コンテナーごとに 1 回ではなく、JVM に 1 回だけ読み込まれることを常に想定して、2 つのオプションがあります (その場合、別のアプローチが必要になりますが、それでも可能です)。

  • コンパイル時のバイナリ ウィービング: インターセプトするクラスを含むコンテナーの JAR ファイルをウィービングし、新しい JAR を作成して元のファイルを置き換えます。この場合、ブート クラスパスに AspectJ ランタイム JAR のみが必要です。

  • ロード時のウィービング: AspectJ ウィーバー JAR を JVM のブート クラスパスに配置し、ロード時にターゲット クラスにアドバイスを適用します。

于 2012-11-04T11:50:56.597 に答える