0

リスト インターフェイス内のメソッドにポイントカットするクラスを作成したいと思います。これは、ターゲット(リスト)をアドバイスに追加するまで機能するようです。追加の前後にリストの要素を表示して、(たとえば)何が変更されたかを確認したいのですが、オブジェクトのようにリストを渡すことができないようです。これは私がこれまでに持っているものです。これは target(list) では実行されませんが、それなしでは実行されます:

pointcut addPointCut() : call(boolean List.add(..));

before(List<Integer> list) : addPointCut() && target(list) {
    System.out.println("testing");
    for(Object i : list) {
        System.out.println(i);
    }
}
4

2 に答える 2

0

target(...)型またはポイントカットでのジェネリックの使用this(...)はサポートされていないため、コンパイルは次のエラーで失敗します: parameterized types not supported for this and target pointcuts (erasure limitation). リストから型パラメーターを削除すると、期待どおりに機能するはずです。

于 2016-10-23T11:23:35.877 に答える
0

Nándor の答えは、表示されるコンパイラ エラーについて説明している限り、正しいものです。もう少し進んで、このエラーが発生する理由も説明したいと思います。

まず第一に、問題は AspectJ に直接関係するのではなく、Java がジェネリックを実装する方法に関係しています。読み進める前に、型消去と呼ばれる現象に慣れてください。

タイプ消去は JVM の現実であり、target()andthis()はコンパイル時ではなく実行時に解決されるため、 と の両方がメソッドではなくのメソッドであるという事実から間接的にこれを結論付けることgetTarget()getThis()できJoinPointますJoinPoint.StaticPart。 AspectJ コンパイラ エラー。できる唯一のことはinstanceof、ターゲット リストに追加されるものを動的に決定するために を使用することです。これを行う最もエレガントな方法は、if()ポイントカット式です。

サンプルコードは次のとおりです。

ドライバー アプリケーション:

もう少し興味深いものにするために、2 種類のリストと 2 種類のadd(..)呼び出しを使用します。add(..)目標は、メソッドがどのシグネチャを持っているかに関係なく、対応するリストに追加される整数のみをインターセプトすることです。

package de.scrum_master.app;

import java.util.ArrayList;
import java.util.List;

public class Application {
    public static void main(String[] args) {
        List<Integer> integers = new ArrayList<>();
        integers.add(11);
        integers.add(0, 22);
        integers.add(33);

        List<String> strings = new ArrayList<>();
        strings.add("foo");
        strings.add(0, "bar");
        strings.add("zot");
    }
}

側面:

package de.scrum_master.aspect;

import java.util.List;

@SuppressWarnings({"rawtypes", "unchecked"})
public aspect GenericsAspect {
    pointcut addPointCut(List list, Object newElement) :
        !within(GenericsAspect) &&            // avoid stack overflow due to recursion
        call(* List.add(..)) &&               // intercept all calls to List.add
        args(.., newElement) &&               // capture last method parameter
        if(newElement instanceof Integer) &&  // only capture added int/Integer elements
        target(list);                         // target is a List

    before(List list, Object newElement) :
        addPointCut(list, newElement)
    {
        System.out.println(thisJoinPoint + " -> new element = " + newElement);
        for(Object i : list)
            System.out.println("  " + i);

        // Type erasure in action:
        // During runtime there is no such thing as List<Integer>, only a raw List.
        // Thus, we can easily add a String to a list declared as List<Integer>.
        list.add("#" + newElement + "#");
    }
}

コンソール ログ:

call(boolean java.util.List.add(Object)) -> new element = 11
call(void java.util.List.add(int, Object)) -> new element = 22
  #11#
  11
call(boolean java.util.List.add(Object)) -> new element = 33
  22
  #11#
  11
  #22#

さらに質問はありますか?

于 2016-10-23T15:00:43.223 に答える