[英]About Policy Enforcement with AspectJ
I am using Aspectj for project-wide policy enforcement.我正在使用 Aspectj 执行项目范围的策略。
One thing I am trying to implement now is that there should be no logic in any setter methods except simple validation with Guava's Preconditions.check*
methods.我现在要实现的一件事是,除了使用 Guava 的
Preconditions.check*
方法进行简单验证之外,任何 setter 方法中都不应该有任何逻辑。
public pointcut withinSetter() :
withincode(public void set*(*));
public pointcut inputValidation() :
call(public void Preconditions.check*(*));
public pointcut setFieldValue() : set(* *);
public pointcut entity() : within(com.mycompany.BaseEntity+);
declare warning :
entity() && withinSetter() && !setFieldValue() && !inputValidation():
"Please don't use Logic in Setters";
This works as expected, generating warnings for any non-setter code.这按预期工作,为任何非 setter 代码生成警告。 However, it fails for constructs like this:
但是,对于这样的构造,它会失败:
public void setFoo(final String newFoo) {
Preconditions.checkNotNull(newFoo); // this is OK
Preconditions.checkArgument(
newFoo.matches("\\p{Alpha}{3}"), // this generates a warning
// because String.matches()
// is called
"Foo must have exactly 3 characters!");
this.foo = newFoo;
}
So what I am looking for is a construct that would allow any code, as long as it happens inside the parameters to a Preconditions.check*
call.所以我正在寻找的是一个允许任何代码的构造,只要它发生在
Preconditions.check*
调用的参数内。 Is there such a pointcut?有这样的切入点吗?
I know it is an old question, but I just stumbled across it while searching for something else.我知道这是一个老问题,但我只是在寻找其他东西时偶然发现了它。
The answer is no, because in JVM bytecode there is no such thing as "logic inside a check*
call".答案是否定的,因为在 JVM 字节码中没有“
check*
调用中的逻辑”之类的东西。 For example, newFoo.matches(..)
is evaluated before the result is passed to Preconditions.checkArgument(..)
, very much like this:例如,
newFoo.matches(..)
在结果被传递给Preconditions.checkArgument(..)
之前被评估,非常像这样:
boolean match = newFoo.matches("\\p{Alpha}{3}");
Preconditions.checkArgument(match, "Foo must have exactly 3 characters!");
If the code was written like this, you would issue a warning anway, so why not if the same Java code, possibly resulting in similar or identical byte code, is written as a nested call?如果代码是这样编写的,您会发出警告,那么为什么不将相同的 Java 代码(可能导致相似或相同的字节代码)编写为嵌套调用呢?
;-)
Update: I have created a little example:更新:我创建了一个小例子:
public class Application {
public static void main(String[] args) {
String newFoo = "Scrum";
boolean match = newFoo.matches("\\p{Alpha}{3}");
checkArgument(
match,
"Foo must have exactly 3 characters!"
);
checkArgument(
newFoo.matches("\\p{Alpha}{3}"),
"Foo must have exactly 3 characters!"
);
}
private static void checkArgument(boolean status, String errorMessage) {
if (!status)
System.out.println(errorMessage);
}
}
If you dump the byte code using javap -c Application
you see this:如果您使用
javap -c Application
转储字节码,您会看到:
Compiled from "Application.java"
public class Application extends java.lang.Object{
public Application();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16; //String Scrum
2: astore_1
3: aload_1
4: ldc #18; //String \p{Alpha}{3}
6: invokevirtual #20; //Method java/lang/String.matches:(Ljava/lang/String;)Z
9: istore_2
10: iload_2
11: ldc #26; //String Foo must have exactly 3 characters!
13: invokestatic #28; //Method checkArgument:(ZLjava/lang/String;)V
16: aload_1
17: ldc #18; //String \p{Alpha}{3}
19: invokevirtual #20; //Method java/lang/String.matches:(Ljava/lang/String;)Z
22: ldc #26; //String Foo must have exactly 3 characters!
24: invokestatic #28; //Method checkArgument:(ZLjava/lang/String;)V
27: return
}
As you can see, the byte code of lines 3-13 versus 16-24 in the dump is identical except for the storing and re-loading of the boolean value.如您所见,转储中第 3-13 行与第 16-24 行的字节码是相同的,除了 boolean 值的存储和重新加载。 Maybe this illustrates what I have said before.
也许这说明了我之前所说的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.