我有一个接受任何类型作为参数的泛型方法 例如,我想要一个切入点匹配对方法的调用仅与' String'键入作为其参数。最终,要求是将建议的执行范围限制为“字符串”。参数。
这是我的通用类和方法:
public class Param<T> {
public T execute(T s){
return s;
}
}
主类:我的应用程序使用Boolean和String作为参数调用方法。
public static void main(String[] args) {
Param<String> sp = new Param<String>();
String rs = sp.execute("myString"); //want a joint point
Param<Boolean> bp = new Param<Boolean>();
Boolean rb = bp.execute(true); //dont want a joint point
}
以下切入点对String和Boolean参数都有效(实际上适用于任何类型)。但是我希望切入点仅在参数类型为String时拦截方法调用。
@Pointcut("call(* com.amazon.auiqa.aspectj.generics.Param.execute(**))")
void param(){}
@Pointcut("execution(Object com.amazon.auiqa.aspectj.generics.Param.execute(Object))")
void param(){}
以下哪些不适合我:
@Pointcut("execution(String com.amazon.auiqa.aspectj.generics.Param.execute(String))")
@Pointcut("call(String com.amazon.auiqa.aspectj.generics.Param.execute(String))")
我想知道是否有可能实现我想在这里实现的目标。我想用方法返回类型做同样的事情。
答案 0 :(得分:0)
您不能使用AspectJ,也不能使用任何其他字节码操作库,因为泛型类型信息实际上已从编译的字节码中删除(从Java 9开始),因此您的泛型方法变为public Object execute(Object s)
,因为类型参数T
无限制。有关详细信息,请参阅Java文档中的Type Erasure。
虽然原始方法签名以元数据的形式保留,但编译器可以在编译通用代码时检查是否遵守类型边界,但这无助于您以任何方式确定实例的泛型类型参数该类的实例化,因为根本不存在该信息。
答案 1 :(得分:0)
其他帖子提到的关于Java擦除的内容是真的。
AspectJ 5不允许在切入点表达式和类型模式中使用类型变量。相反,使用类型参数作为其签名一部分的成员将通过其擦除进行匹配。 Java 5定义了用于确定类型擦除的规则,如下所示。
让
|T|
代表某种类型T
的删除。然后:
参数化类型
T<T1,...,Tn>
的删除为|T|
。例如,List<String>
的删除是List
。嵌套类型
T.C
的删除是|T|.C
。例如,嵌套类型Foo<T>.Bar
的删除是Foo.Bar
。数组类型
T[]
的删除是|T|[]
。例如,List<String>[]
的删除是List[]
。类型变量的擦除是其最左边的边界。例如,类型变量
P
的擦除为Object
,类型变量N extends Number
的擦除为Number
。
您可以找到更多here。
但是,您可以执行以下操作:
execute
的所有Param
方法执行。String
按参数类型过滤instanceof
参数的要求。请记住,需要加号(+
)来表示通用。
这是一个例子,
@Component
@Aspect
public class ParamAspect {
@Pointcut("execution(public * com.amazon.auiqa.aspectj.generics.Param+.execute(..))")
public void pointcut() {
}
@Before("pointcut()")
public void intercept(JoinPoint jp) {
System.out.println(
"Entering class: " + jp.getSignature().getDeclaringTypeName() +
" - before method: " + jp.getSignature().getName());
// check for argument type of String
Object[] args = jp.getArgs();
if (args.length == 1) {
if (args[0] instanceof String) {
System.out.println("1. parameter type is string");
} else {
System.out.println("2. parameter type is not string");
}
}
}
}