如何为采用任意数量的参数实现Serializable或基本类型的方法编写Pointcut?
E.g。切入点应匹配:
methodA(String str, int i)
methodB(String str, String str2, List<String> list)
但不是
methodC(String str, DataX data)
其中DataX不可序列化
答案 0 :(得分:1)
我不知道在切入点中指定那种条件,所以我唯一拥有的东西是非常昂贵的,因为它涉及运行时检查 - 但它可以做你想要的:
驱动程序应用程序:
package de.scrum_master.app;
import java.io.Serializable;
public class Application {
public static class MyNonSerializable {}
public static class MySerializable implements Serializable {
private static final long serialVersionUID = 1L;
}
private static MyNonSerializable one() {
return new MyNonSerializable();
}
static MySerializable two(int i, String string) {
return new MySerializable();
}
static String three(int i, String string, MyNonSerializable myNonSerializable) {
return "foo";
}
static MyNonSerializable four(int i, String string, MySerializable mySerializable) {
return new MyNonSerializable();
}
static void five(MyNonSerializable myNonSerializable) {
}
static int six(MySerializable mySerializable) {
return 11;
}
public static void main(String[] args) {
one();
two(11, "foo");
three(11, "foo", new MyNonSerializable());
four(11, "foo", new MySerializable());
five(new MyNonSerializable());
six(new MySerializable());
}
}
现在,无论返回类型如何,我们都希望使用零参数或任意数量的Serializable
参数来拦截执行。符合此条件的方法为main
,one
,two
,four
,six
。
运行时类型检查的方面:
package de.scrum_master.aspect;
import java.io.Serializable;
public aspect MethodsWithSerializableArgumentsAspect {
before() : execution(* *(..)) {
boolean nonSerializableArgumentFound = false;
for (Object arg : thisJoinPoint.getArgs()) {
if (!(arg == null || arg instanceof Serializable)) {
nonSerializableArgumentFound = true;
break;
}
}
if (nonSerializableArgumentFound)
return;
System.out.println(thisJoinPoint);
}
}
控制台日志:
execution(void de.scrum_master.app.Application.main(String[]))
execution(Application.MyNonSerializable de.scrum_master.app.Application.one())
execution(Application.MySerializable de.scrum_master.app.Application.two(int, String))
execution(Application.MyNonSerializable de.scrum_master.app.Application.four(int, String, Application.MySerializable))
execution(int de.scrum_master.app.Application.six(Application.MySerializable))
Tadaa! :-)
现在,如果您还要排除返回不可序列化对象的方法,则应将输出限制为main
,two
,six
。你可以这样做:
package de.scrum_master.aspect;
import java.io.Serializable;
public aspect MethodsWithSerializableArgumentsAspect {
Object around() : execution(* *(..)) {
boolean nonSerializableArgumentFound = false;
for (Object arg : thisJoinPoint.getArgs()) {
if (!(arg instanceof Serializable)) {
nonSerializableArgumentFound = true;
break;
}
}
Object result = proceed();
if ((result == null || result instanceof Serializable) && !nonSerializableArgumentFound)
System.out.println(thisJoinPoint);
return result;
}
}
控制台日志:
execution(Application.MySerializable de.scrum_master.app.Application.two(int, String))
execution(int de.scrum_master.app.Application.six(Application.MySerializable))
execution(void de.scrum_master.app.Application.main(String[]))
请注意,为了对返回值进行运行时检查,我们只能在方法终止后打印结果。因此,main
位于日志输出的末尾,而不是第一个解决方案中的开头。
更新:我忘了解释为什么我们需要检查广告并返回null
的值。这是因为我们希望接受null
或void
作为Serializable
,但实际上null instanceof Serializable
是假的。
更新2 - 没有运行时类型检查的静态切入点解决方案:
好吧,我只是在吃一个苹果(不,它没有掉到我的头上),突然有了这个想法。它实际上工作得很好,正是你想要的:
package de.scrum_master.aspect;
import java.io.Serializable;
public aspect MethodsWithSerializableArgumentsAspect {
pointcut returnsSerializable() :
execution((Serializable+ || byte || short || int || long || float || double || char || boolean || void) *(..));
pointcut hasNonSerializableArguments() :
execution(* *(.., !(Serializable+ || byte || short || int || long || float || double || char || boolean || void), ..));
before() : returnsSerializable() && !hasNonSerializableArguments() {
System.out.println(thisJoinPoint);
}
}
BTW,Serializable+
表示“Serializable及其所有子类或实现类”。
享受!