Nándor 的回答是正确的,因为他描述了您看到的编译器错误。我想进一步解释一下为什么会出现此错误:
首先,问题与 AspectJ 没有直接关系,而是与 Java 如何实现泛型有关。在继续阅读之前,请先熟悉一种称为类型擦除的现象。
好吧,因为类型擦除是 JVM 的现实,并且因为target()
andthis()
是在运行时而不是编译时解决的——你可以从两者的方法间接得出这一点,而不是方法getTarget()
——你想做的事情不起作用,因此导致AspectJ 编译器错误。您唯一能做的就是使用它来动态确定添加到目标列表中的内容。最优雅的方法是切入点表达式。getThis()
JoinPoint
JoinPoint.StaticPart
instanceof
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#
还有其他问题吗?