java - 关于使用 AspectJ 执行策略

标签 java aop aspectj pointcuts

我正在使用 Aspectj 执行项目范围的策略。

我现在尝试实现的一件事是,除了使用 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";

这按预期工作,为任何非 setter 代码生成警告。但是,对于这样的构造它会失败:

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

因此,我正在寻找的是一种允许任何代码的构造,只要它发生在 Preconditions.check* 调用的参数内部。有这样的切入点吗?

最佳答案

我知道这是一个老问题,但我只是在搜索其他内容时偶然发现了它。

答案是否定的,因为在 JVM 字节码中没有“check* 调用中的逻辑”这样的东西。例如,newFoo.matches(..) 之前被计算,结果被传递给 Preconditions.checkArgument(..),非常像这样:

boolean match = newFoo.matches("\\p{Alpha}{3}");
Preconditions.checkArgument(match, "Foo must have exactly 3 characters!");

如果代码是这样写的,您无论如何都会发出警告,那么如果将可能导致相似或相同字节代码的相同 Java 代码编写为嵌套调用,为什么不呢? ;-)


更新:我创建了一个小例子:

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

如果使用 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

}

如您所见,转储中第 3-13 行和第 16-24 行的字节码除了 boolean 值的存储和重新加载外是相同的。也许这说明了我之前所说的。

关于java - 关于使用 AspectJ 执行策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5804001/

相关文章:

java - 可移植开源 Java Web 服务器推荐?

java - 如何在 java 8 中使用 IntelliJ 中的集合工厂方法

c# - 如何将方面应用于特定元素(例如,对于 LocationInfo 类型参数或 PropertyInfo)?

java - Spring AOP 代理没有按预期工作

java - 关于实现扩展接口(interface)的方法的建议

java - 如何将 Java 中的 SortedSet 转换为 Scala 中的 Seq

java - p6spy 找不到适合 com.mysql.jdbc.Driver 的驱动程序

c# - 如何在.Net 平台上开始面向切面编程?

spring - 为什么在Spring中使用AOP进行事务管理?

java - 一个带有aop的tomcat应用的拦截方法