5

AspectJ を使用して、初期化されたすべてのオブジェクトにいくつかのメソッドを注入する必要があります。

私はこれを使って考えました:

pointcut vistaInjection(Object o)
    : initialization(java.lang.Object.new() ) 
    && target(o)
    && !within(objectAspect);

before(Object o): methodInjection(o){System.err.println("INIT");}

オブジェクトの初期化をポイントカットするため、これらのメソッドを他のすべてのオブジェクトの一部であるオブジェクトに直接注入できます。

しかし、うまくいきません。理由はわかりますか?または、初期化されたすべてのオブジェクトがポイントカットされることを 100% 確実にする他の方法は何でしょうか? *.new は、文字列、リストなどには機能しません。

ありがとうございました!

4

2 に答える 2

19

ユーザー selig は正しいです。おそらく、すべてのオブジェクトの作成、特に JDK/JRE クラスの作成をインターセプトしたくないでしょう。しかし、それが価値があるために、何が機能し、どのように機能し、何が機能しないかについての説明は次のとおりです。

ちょっとしたドライバー アプリケーション:

public class Application {
    public static void main(String[] args) {
        new Application();
        new String();
    }
}

さまざまなタイプのコンストラクター関連のポイントカット/アドバイスを含むアスペクト:

public aspect ObjectCreationAspect {
    before() : preinitialization(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : initialization(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : call(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : execution(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }
}

ウーブン ドライバー アプリケーションの出力:

call(Application())
preinitialization(Application())
initialization(Application())
execution(Application())
call(java.lang.String())

説明:

AspectJ にはさまざまな種類のウィービングがあります。

  • Compile-time weaving (CTW): ajc (AspectJ コンパイラ) によってコンパイルされたクラスのみを織り込むことができます。これには、JDK/JRE クラスと、ソースからコンパイルしないサードパーティ ライブラリも含まれません。上記のサンプル出力は、コンパイル時のウィービングの効果を示しています。
  • バイナリ ウィービング (BW): AspectJ コンパイラは、アスペクト コードを既存のバイト コードに直接コンパイルするために使用されます。これは、サードパーティのライブラリだけでなく、独自のプリコンパイル済みアプリケーション クラスでも機能します。AspectJ コンパイラの in-pathにrt.jarを配置すると、理論的には JDK/JRE クラスでも動作します。JDK/JRE の織り方は少しトリッキーですが、私は以前にやったことがあります。アプリケーションを起動するときに JDK/JRE の boot-classpath の先頭に追加する、いくつかの JDK クラスを組み合わせたrt.jarの新しく編まれたバージョンまたは単なる小さな JAR ファイルを生成できます。
  • Load-time weaving (LTW): 基本的にこれは BW で​​すが、クラスの読み込み中に動的に行われます。この AspectJ シナリオでは、アスペクト ウィーバーの影響下でクラスローダーによってロードされるクラスのみを織り込むことができます。したがって、独自のコードとサードパーティのライブラリでは機能しますが、通常、アスペクト ウィーバーがロードされる前にロードされる JDK/JRE ブートストラップ クラスでは機能しません。これは卵と鶏の問題です。ウィーバーは JRE をロードする前に JRE を実行する必要がありますが、JRE クラスをウィービングするには、それらのクラスがブートストラップされる前にウィーバーがそこにいる必要があります。

これで簡単にできることは、独自のコードまたはサードパーティのコードから JDK/JRE コンストラクターへの呼び出しcall(java.lang.String())をインターセプトすることです。これは、ログ出力行で. ただし、JRE クラスから JRE クラスへの内部呼び出しをインターセプトすることはできません。

そうは言っても、あなたはどんな恐ろしいことをしたいのだろうと本当に思います。つまり、あなたはそれを説明しますが、それは途方もない設計エラーのように聞こえます。または、車輪を再発明して、すでに存在するある種のプロファイラーまたはデバッガーを書きたいとします。個々のオブジェクトの作成を傍受することで何を期待できますか? ログに記録している文字列だけの場合、アプリケーションの速度が大幅に低下し、メモリ消費が大幅に増加し、さらに多くのオブジェクトが作成されます。自分が本当にやりたいことは何なのか、もう一度考えてみてください。そうすれば、あなたの目標を達成するためのスマートな方法を提案できるかもしれません。

于 2013-07-08T22:02:31.560 に答える
1

やってみました

pointcut vistaInjection(Object o)
    : (initialization(*.new()) || (initialization(*.new(..)))
    && target(o)
    && !within(objectAspect);

つまり、何かを呼び出し.new()て、引数をまったく許可せず、いくつかの引数を許可します。

注 - おそらく、すべてのオブジェクトの作成を取得したくないでしょう..それらで何をするつもりですか!

于 2013-06-27T16:26:42.220 に答える