AspectJ参数化类型不支持目标切入点

时间:2016-10-21 17:22:39

标签: java aspectj pointcuts

我想在列表界面中创建一个指向方法的类。这似乎有效,直到我将目标(列表)添加到我的建议。我想在添加之前和之后查看列表的元素(例如)看看有什么变化,但我似乎无法通过我的列表,因为我会对象。这是我到目前为止,这不是与目标(列表)一起运行,但没有它运行:

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);
    }
}

2 个答案:

答案 0 :(得分:0)

不支持使用类型target(...)this(...)切入点中的泛型,编译将因此错误而失败:parameterized types not supported for this and target pointcuts (erasure limitation)。从列表中删除type参数,它应该按预期工作。

答案 1 :(得分:0)

Nándor的回答是正确的,因为他描述了你看到的编译器错误。我想更进一步,并解释 为什么 您收到此错误:

首先,问题与AspectJ没有直接关系,而是与Java如何实现泛型有关。在继续阅读之前,请熟悉一种名为type erasure的现象。

好吧,因为类型擦除是一个JVM现实,并且因为target()this()在运行时而不是编译时被解析 - 你可以间接地从getTarget()getThis()JoinPointJoinPoint.StaticPart而不是instanceof的方法 - 您想要做的事情无法工作,从而导致AspectJ编译器错误。您唯一能做的就是使用if()来动态确定添加到目标列表的内容。最优雅的方法是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#

控制台日志:

Dockerfile

还有其他问题吗?