2009-07-03 12 views
4

このコードを動作させる方法はありますか?Java:アノテーションベースのコードインジェクションのための簡単な技術?

LogonControl.java

@Audit(AuditType.LOGON) 
public void login(String username, String password) { 
// do login 
} 

AuditHandler.java

public void audit(AuditType auditType) { 
// persist audit 
} 

終局は、各時間ログイン()が呼び出されることを、監査()は、適切なaudittypeと、呼ばれています。

私はAOPがおそらくこれの解決策であると考えていますが、私はできるだけシンプルにしたいと思います(私が見てきたAspectJチュートリアルは非常に複雑な注釈を持っています)。

注:私は、監査を呼び出すメソッドを事前に定義する必要はありません。私はこれを拡張可能なフレームワーク用に作成しており、他のメンバーはそれを使用する必要があります。

+0

コードは何をすべきですか? @Auditでアノテーションされたメソッドが呼び出されるたびにaudit()メソッドが呼び出されるべきですか? –

+0

@Esko Luontola - はい、正確です。 –

答えて

14

はわずかばかりのJUnitのテストランナーのように、@Auditと方法を注釈は容易である:

ハンドラは
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface Audit { 

    Class<? extends Handler> handler(); 
} 

public interface Login { 

    void login(String name, String password); 
} 

public class LoginImpl implements Login { 

    @Audit(handler = LoginHandler.class) 
    public void login(String name, String password) { 
     System.out.println("login"); 
    } 

} 

@Auditは以下のように定義されます

interface Handler { 

    void handle(); 
} 

class LoginHandler implements Handler { 

    public void handle() { 
     System.out.println("HANDLER CALLED!"); 
    } 
} 

実際のコード:

public class LoginFactory { 

    private static class AuditInvocationHandler implements InvocationHandler { 

     private final Login realLogin; 

     public AuditInvocationHandler(Login realLogin) { 
      this.realLogin = realLogin; 
     } 

     public Object invoke(Object proxy, Method method, Object[] args) 
         throws Throwable { 
      Method realMethod = realLogin.getClass().getMethod(
             method.getName(), 
             method.getParameterTypes()); 
      Audit audit = realMethod.getAnnotation(Audit.class); 

      if (audit != null) { 
       audit.handler().newInstance().handle(); 
      } 

      return method.invoke(realLogin, args); 
     } 
    } 

    public static Login createLogin() { 
     return (Login) Proxy.newProxyInstance(
       LoginFactory.class.getClassLoader(), 
       new Class[]{Login.class}, 
       new AuditInvocationHandler(new LoginImpl())); 
    } 
} 

@Test:

Login login = LoginFactory.createLogin(); 
    login.login("user", "secret"); 
    login.logout(); 

出力:

 
HANDLER CALLED! 
login 
logout 
+0

最高のソリューションのようです。私はコードをそのままにして注釈を追加できることを期待していましたが、多くの研究の後では可能ではないと私は考えています。 乾杯。 –

5

完了です。SpringまたはGuiceを使用してください。

あなたがknow how wheels workにしたい場合、またはあなたが非常に軽い何かをすることができると思うのであれば、自分自身を転がすことは理にかなっています。あなたがそれを実行する前に両方が真であることを確かめてください。リフレクションを使用して

+0

私を信頼する - 私は自分自身を転がす欲求がないが、春は私の用途のためにOTTです。私はGuiceを見て、まずそれは良い見えます。 –

+0

私のポイントは、あなたが恩恵を受けるためにすべてのSpringを飲み込む必要がないということでしょう。 Spring AOPはAspectJに比べてかなり軽量です(それほど強力ではありません)。それはあなたの必要に応じてうまくいくかもしれません。 AOPに関係する小さなサブセットだけで、Springのすべてを処理する必要はありません。私は、Springがこれらの状況でうまく動作することを発見しました。それは、完全な書き換えを要求することなく、狭い目的のために従来のアプリに導入することが可能です。それを試してみてください。 – duffymo

+0

Springには既に組み込みのトレース・アスペクトがあります。あなたは少しの設定と新しいコードでは望みのことをすることができるかもしれません。 – duffymo

1

はGuiceの中に傍受する方法を見てください:http://code.google.com/p/google-guice/wiki/AOP

同様のアプローチは、任意のAOPフレームワークで動作するはずです。

+0

ありがとう。 この行は少し怖いです: "Guiceによって構築されていないインスタンスでメソッドの代行受信を使用することはできません。 これは、メソッド傍受が機能する前にGuice.getInstance(LogonController.class)を使用しなければならないことを意味します。 これは別のAOPフレームワークで可能かどうかを調べます。 –

+0

これはGuiceがオブジェクトを構築する必要があることを意味しますが、Guiceに構築を依頼する必要はありません。オブジェクトは、Guiceによって構築された別のオブジェクトに注入することができます。 基本的に、Guiceはdfaが提供したソリューションでFactoryを置き換えます。 – NamshubWriter

関連する問題