0

我想创建一个指向列表接口中方法的类。这似乎有效,直到我将目标(列表)添加到我的建议中。我想在添加到(例如)之前和之后查看列表的元素,看看发生了什么变化,但我似乎无法像传递对象那样传递我的列表。这是我到目前为止所拥有的,它不与目标(列表)一起运行,但在没有它的情况下运行:

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()——你想做的事情不起作用,因此导致AspectJ 编译器错误。您唯一能做的就是使用它来动态确定添加到目标列表中的内容。最优雅的方法是切入点表达式。getThis()JoinPointJoinPoint.StaticPartinstanceofif()

这是一些示例代码:

驱动应用:

为了让事情变得更有趣,我们使用两种类型的列表和两种类型的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 回答