3
/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

サービスという名前のこのポイントカットは、サーバー オブジェクトのパブリック メソッドが呼び出されたときに、プログラムの実行中のポイントを選択します。また、サービス ポイントカットを使用するすべてのユーザーが、メソッドが呼び出されている Server オブジェクトにアクセスできるようになります。( https://eclipse.org/aspectj/doc/released/progguide/language-anatomy.htmlから取得)

私は AspectJ のポイントカットを理解しようとしていますが、現時点ではかなり混乱しています。私の主な質問は、上記のポイントカットをどのように読み、その意味をどのように「パズル」しますか?

私の混乱を説明するために、ゼロから構築してみましょう。

次のポイントカットは、任意のオブジェクトへのすべてのパブリック メソッド呼び出しをインターセプトしますよね?

/* 1 */ pointcut services() : call(public * *(..))

さて、これはどうですか:

/* 2 */ pointcut services() : call(public * Server.*(..)) 

Server オブジェクトのパブリック メソッドが呼び出されると、任意のポイントがインターセプトされると思います。

では、ここから最初の例 0 に到達するにはどうすればよいでしょうか。で、どうやって読むの?

ポイントカットを構築するときに、最初にパラメーター リストを提供しますか?

/* 3a */ pointcut services(Server s) : call(public * *(..))

上の2番と同じですか?(私はそれが機能しないと感じています。もし機能した場合、番号 1 のように、すべてのパブリック メソッド呼び出しを「インターセプト」します。)とにかく、次は同じでしょうか? (私はsまだネイティブのポイントカットで「キャプチャ」していないので、実際に定義することはできませんね?)

/* 4a */ pointcut services(Server /* only type, no variable */) : call(public * *(..))

または、次のように、ターゲット オブジェクトを「キャプチャ」するために、ネイティブ ポイントカットを指定することから始めますか。

/* 3b */ pointcut services() : target(s) && call(public * *(..))

任意のオブジェクトのすべてのパブリック メソッド呼び出しをまだインターセプトすると思いますか?

以下は、Server オブジェクトの呼び出しのみをインターセプトし、そのオブジェクトを "キャプチャ" するために機能しますか?

/* 5 */ pointcut services(/*nothing here*/) : target(s) && call(public * Server.*(..))

ここで、元のポイントカットに戻ります。

/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

と同じですか

/* 6 */ pointcut services(Server s): target(s) && call(public * Server.*(..))

要約すると、0 の解読をどのように開始しますか?

最初にポイントカットを見てtarget、次にポイントカットのパラメータータイプを見て、 services「裏返し」/「右から左」に読みますか? それとも、最初にパラメータ リストを調べてから、servicesポイントカットを調べて、引数がどこから来たのか (つまりtarget(s)) を調べますか?

それとも、これを複雑にしすぎていますか?これを理解するのに役立つ重要な部分がどこかに欠けていますか?

編集:Server sマニュアルでは左から右に説明していますが、まだ「実行」していない場合、パラメータへの引数はどこから来るのtarget(s)でしょうか?

4

1 に答える 1

4

1: はい、すべてのパブリック メソッド呼び出しをインターセプトします。

2:として宣言されたオブジェクトに対するすべての public メソッド呼び出しをインターセプトしますServerが、 0 は のインスタンスであるオブジェクトに対するすべてのパブリック呼び出しをインターセプトしますServerセマンティクスを参照してください。

3a:sバインドされていないため、コンパイルされません:

[ERROR] formal unbound in pointcut
        .../src/main/aspect/MyAspect.aj:18
pointcut services(Server s): call(public * *(..));

4a: インターフェイスでメソッドを宣言するときにパラメーターに名前を付ける必要があるのと同様に、構文が無効です。

[ERROR] Syntax error, insert "... VariableDeclaratorId" to complete FormalParameterList
        .../src/main/aspect/MyAspect.aj:18
pointcut services(Server): call(public * *(..));
                  ^

3b: どちらも有効でsはありません。宣言されていません:

[WARNING] no match for this type name: s [Xlint:invalidAbsoluteTypeName]
        .../src/main/aspect/MyAspect.aj:18
pointcut services(): target(s) && call(public * *(..));

5: 3b と同様、s宣言されていません。

6: 0 と同じではありません。パブリックServerメソッドの呼び出し (つまり で宣言Server) のみをServerインスタンスに一致させます。

Github リポジトリでさまざまなケースを説明しました。ブランチを切り替えて試してみてください。6 に基づいて、aspect7 ブランチに追加のケースがあり、そこでオーバーライドhashCode()Serverます。

理解を深めるために、自分で試してみることができます (またそうすべきです)。


最後の質問に答えるために、ポイントカットの引数は、アドバイスのパラメーターとして提供することにより、アドバイスの呼び出しのターゲットにアクセスしたい (アクセスできるようにしたい) という事実から来ています。アドバイスのシグネチャには、参照されるすべてのポイントカットのパラメーターが含まれている必要があり、ポイントカット パラメーターはアドバイス内のパラメーターを参照する必要があります。

したがって、Serverアドバイスにパラメーターを含めるには、ポイントカットでそれが必要であり、ポイントカット定義で何かにバインドする必要があります。

于 2015-03-11T13:58:57.390 に答える