2017-12-26 10 views
0

私はAspectJに関する経験はありませんが、最近は実装するタスクがあり、いくつかのAspectJチュートリアルを読みました。私の解決策。特定のアノテーションを持つクラスメンバのメソッドを呼び出すためのポイントカットパターン

タスクは次のとおりです。 私はいくつかのメソッドb()を持つクラスAを持ち、このクラスのオブジェクトは他のクラスのフィールドとして含まれています。 私はこれらのフィールドに@Cというアノテーションを付けてアノテーションを付け、タイプAとアノテーション@Cのフィールドでメソッドb()を呼び出すたびにこのアノテーション値を取得したいと思います。

簡体コード:

class A{ 
    field1; 
    field2; 
    field3; 

     void b(String[] fieldsToIgnore){ 
     doSomething with fields 1,2,3 (excluding fields from fieldsToIgnore array) 
    } 
     } 

    class B{ 
     @C(value="field1,field2") 
     A fieldA; 
     } 


     //Here when I want to weaver my aspect - before I call to method b() on fieldA with annotation @C - I want to get annotation value and to pass it as an argument to method b() 
     new B.fieldA.b() 

私は助言のために私が正しいポイントカットを記述するのに役立ちます。私はまた、私のアドバイスメソッドからメソッドb()にデータをどのように転送することができるのかよく理解できません - それはまったく可能ですか?

は、任意の助けに感謝します - あなただけのMTは「いいえ、それは不可能です」言う場合でも - あなたはすでに大規模とにかくリフレクションを使用している場合、それは、私に多くの時間を節約し、神経:)実は

+0

私が答える前に私はあなたに明確にして欲しい:「データをアドバイスからメソッド 'b()'に転送することはどういう意味ですか? (疑似)コードを編集し、そのデータをそのメソッドでどのように使用するかを教えてください。ところで、あなたは 'A'フィールドとそのフィールドに割り当てられたオブジェクトの接続に関していくつかの手帳を行う準備ができていますか?なぜなら、これは可能なのですが、アプリケーションの設計上、少し面倒です。 – kriegaex

+0

私の擬似コードを更新しました。主なアイデアは、メソッドの実行中にこれらのフィールドが無視されるように、注釈値にリストされたフィールド名のリストをメソッドb()に渡すことです。 –

+0

あなたの 'new B()。fieldA.b()'(ところで、括弧を忘れてしまった)メソッドの署名 'void b(String [] fieldsToIgnore)'と一致しないため、コンパイルされません。 AspectJの使用を開始する前でさえ、これはJavaの問題です。さらに、アプリケーションが(a)アプリケーションがアスペクトについて知っていて、アスペクトなしでは動作できない場合、(b)アスペクトがアノテーションに文字列としてリストされているフィールド名をあまりにも必要としている場合にのみ、アプリケーションの設計に間違いがあります。したがって、リファクタリング時に中断されます。これはクロスカッティングの問題ではなく、可能な場合でもAOPの使用例はありません。 – kriegaex

答えて

1

ます - これはコードをリファクタリングしないという言い訳ではなく、そうし続けることを望みますが、実際には、混乱をさらに悪化させるために実際にAspectJは必要ありません。反射フィールドアクセスのための

ヘルパークラス:

package de.scrum_master.app; 

import java.lang.reflect.Field; 
import java.util.Arrays; 
import java.util.List; 

public class FieldHelper { 
    public static Field getField(Class<?> clazz, String fieldName) { 
    Field field; 
    try { 
     field = clazz.getDeclaredField(fieldName); 
    } catch (NoSuchFieldException | SecurityException e) { 
     throw new RuntimeException("Reflection problem", e); 
    } 
    field.setAccessible(true); 
    return field; 
    } 

    public static Field[] getFields(Class<?> clazz) { 
    Field[] fields = clazz.getDeclaredFields(); 
    for (Field field : fields) 
     field.setAccessible(true); 
    return fields; 
    } 

    public static List<String> extractIgnoredFieldsList(Class<?> clazz, String fieldName) { 
    return Arrays.asList(
     getField(clazz, fieldName) 
     .getAnnotation(IgnoreFields.class) 
     .fieldNames() 
    ); 
    } 
} 

マーカー注釈:呼び出されるメソッドと

package de.scrum_master.app; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface IgnoreFields { 
    public String[] fieldNames(); 
} 

クラス:

あなたはこのようにそれを単に行うことができます
package de.scrum_master.app; 

import java.lang.reflect.Field; 
import java.util.Date; 
import java.util.List; 

import static de.scrum_master.app.FieldHelper.*; 

public class A { 
    int number = 11; 
    String text = "Hi there!"; 
    Date date = new Date(); 
    String optionalText = "I am not really always needed"; 
    int optionalNumber = 123; 

    public void doSomething(List<String> ignoredFields) { 
    for (Field field : getFields(this.getClass())) { 
     if (!ignoredFields.contains(field.getName())) { 
     try { 
      System.out.println(field.getName() + " = " + field.get(this)); 
     } catch (IllegalArgumentException | IllegalAccessException e) { 
      throw new RuntimeException("Reflection problem", e); 
     } 
     } 
    } 
    } 
} 
注釈付きのメンバーフィールドを持つ

クラス:

package de.scrum_master.app; 

import static de.scrum_master.app.FieldHelper.*; 

public class B { 
    @IgnoreFields(fieldNames = { "optionalText", "optionalNumber" }) 
    A noOptionalsA = new A(); 

    @IgnoreFields(fieldNames = { "text", "number", "date" }) 
    A onlyOptionalsA = new A(); 

    public static void main(String[] args) { 
    B b = new B(); 
    b.noOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "noOptionalsA")); 
    System.out.println("----------------------------------------"); 
    b.onlyOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "onlyOptionalsA")); 
    } 
} 

コンソールログ:

number = 11 
text = Hi there! 
date = Wed Dec 27 18:54:44 ICT 2017 
---------------------------------------- 
optionalText = I am not really always needed 
optionalNumber = 123 

あなたはここで何が起こっているのか理解していない場合、または、あなたはまだ、AspectJの溶液にしてくださいと主張している場合私に知らせてください、そして、私は説明して、そして/または余分なアスペクトコードを提供します。

+0

提供されたソリューションに感謝します。アスペクトの代わりに使うと思うのですが、アスペクトを使用すると、私たちのプロジェクトでロンボクも使用しているので、頭がおかしくなります。 –

+0

**アップデート** **リフレクションベースの例外を実行時の例外にラップするために、コードを少しリファクタリングしました(リフレクションの使用によりメソッドのシグネチャを変更する必要はありません)。** (b)**注釈からの無視されたフィールドリストをヘルパークラスに取得するために、これまでに繰り返された定型文を移動する。 – kriegaex

関連する問題