2

プロジェクト全体のポリシー適用に Aspectj を使用しています。

私が今実装しようとしているのは、グアバのPreconditions.check*メソッドを使用した単純な検証を除いて、どのセッター メソッドにもロジックがあってはならないということです。

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

これは期待どおりに機能し、セッター以外のコードに対して警告を生成します。ただし、次のような構成では失敗します。

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*したがって、私が探しているのは、呼び出しのパラメーター内で発生する限り、任意のコードを許可する構造です。そのようなポイントカットはありますか?

4

1 に答える 1

1

私はそれが古い質問であることを知っていますが、何か他のものを探しているときに偶然見つけました.

check*JVMバイトコードには「呼び出し内のロジック」などがないため、答えはノーです。たとえば、は結果が に渡される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 行目のバイト コードは、ブール値の保存と再読み込みを除いて同じです。たぶん、これは私が以前に言ったことを示しています。

于 2013-08-10T08:43:12.680 に答える