簡體   English   中英

關於 AspectJ 的策略執行

[英]About Policy Enforcement with AspectJ

我正在使用 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 值的存儲和重新加載。 也許這說明了我之前所說的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM