2017-08-16 18 views
3

私はとその多くの用途を調査しており、mixinsを発見しました。AspectJでプライベートフィールドにアクセスするにはどうすればいいですか?

純粋なものを使用した多くの例がありますが、@AspectJアノテーションのみを使用する必要があります。私が達成しようとしています何

は以下の通りです: -

私は私が修正することはできませんクラスを持って、それは私が特定のクラスのメソッドが実行を完了した後に尋問する必要がプライベートクラス変数を持っています。このクラスには、このプライベートクラス変数に関連付けられたgetterメソッドまたはsetterメソッドはありません。

public final class CannotAmend { 

    private Uri privateUri; 

    public final void methodOne(){} 

    public final void methodTwo(){} 

    public final void methodThree(){ 

     privateUri = "something"; 

    } 
} 

私は@AftermethodThree()をキャプチャし、私はprivateUriに設定された値を確認できるようにすることができます側面/ミックスインが必要です。

これは実現可能ですか?

@AspectJ注釈?

これを実現する方法のドキュメント/チュートリアル/例はどこにありますか?

+0

「.aj」構文を使用することはできません。これは、特権的な側面では非常に簡単です。 –

答えて

2

の局面においては、あなたは、リフレクションAPIを使用してプライベートフィールドにアクセスすることができます。

  • 側面が一致する上でメソッドを定義するポイントカット:あなたは二つのことを必要とする局面では

  • そして、@Afterの注釈付きメソッドは、ポイントカットと一致するメソッドが実行された後に実行されるロジックを含みます。プライベートフィールドにアクセスするための文字列定数を使用してサイドノートで
    @Aspect 
    public class MyAspect { 
    
        @Pointcut("execution(* CannotAmend.methodThree(..))") 
        public void methodThreePointcut(){ 
        } 
    
        @After("methodThreePointcut()") 
        public void afterMethod(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException { 
         Object instance = joinPoint.getThis(); 
    
         Field privateUriField = instance.getClass().getDeclaredField("privateUri"); 
         privateUriField.setAccessible(true); 
    
         String privateUri = (String) privateUriField.get(instance); 
         System.out.println(privateUri); // prints "something" 
        } 
    } 
    


は、クリーンなソリューションではありません。将来、変数の名前が変更されたり、削除されたりすると、アスペクトが破損します。

+0

ありがとうございます。これはプライベートフィールドにアクセスできるようにします( "privateUriField.setAccessible(true);トリック)。私はこれが「脆い」解決策であることに同意しますが、これが「唯一の道」であれば、未来の証拠を作る方法はわかりません。どのような選択肢がありますか? (あれば??) – Hector

1

mixinではなく、@Aroundアドバイスを使用してJoinPointを取得し、リフレクトフィールドを取得することができます。たとえば :

@Around("execution(* *.methodThree())") 
public Object getValue(ProceedingJoinPoint pjp) throws Throwable { 
    try { 
     return pjp.proceed(); 
    } finally { 
     System.out.println(pjp.getThis().getClass().getDeclaredField("privateUri").get(pjp.getThis())); 
    } 
} 
+0

解決策は非常に近いですが、プライベートフィールドへのアクセスを許可していません。私はprivateUriField.setAccessible(true)が必要でした。この作業を行うには – Hector

+0

@Hector私のテストでは、 'privateUriField.setAccessible(true)'なしで正常に動作しましたが、 'ajc'によってどのようなバイトコードが生成されるかによって異なります。別の解決策として、いくつかの計測フレームワーク(ByteBuddyなど)を使用し、実行時にクラスをロードする前に元のクラスを変換することができます。 –

関連する問題