2011-12-06 16 views
11

メソッドインターセプタをインスタンスではなくプロバイダにバインドする方法はありますか?メソッドインターセプタをプロバイダにバインドするにはどうすればよいですか?

インターセプタをバインドするには、以下のコードを使用します。インターセプタをプロバイダにバインドしてからアノテーションにバインドする方法はありますか?

bindInterceptor(
    Matchers.any(), Matchers.annotatedWith(ANNOTATION.class), new INTERCEPTOR()); 
+0

何を傍受しようとしていますか? get()メソッドかsetterメソッドか? –

+0

どのような方法でも、メソッドの呼び出しをインターセプトし、実行などを行うパフォーマンス監視システムが理想的です。インターセプタを遅延的に初期化する必要があります。 –

答えて

18

Guiceには、Guiceのことで構築されていないインスタンス上でAOPを許可していません:Guice AOP Limitations

「インスタンスに@を注入-注釈を付けたり、引数なしのコンストラクタによってGuiceのによって作成されなければならない」

をこれがあることを意味しプロバイダで作成されたインスタンスはAOPの候補にはなりません。

あなたのプロバイダが前述の条件でGuiceによってインスタンス化されている限り、あなたのプロバイダはAOPの候補者かもしれません。

ここではこれを示す例です:

AOP注釈:

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) 
@interface AOPExample {} 

プロバイダ:

public class ExampleProvider implements Provider<Example> { 

    @AOPExample 
    public Example get() { 
     System.out.println("Building..."); 
     return new Example(); 
    } 
} 

対象例:

public class Example { 

    @AOPExample 
    public void tryMe() { 
     System.out.println("example working..."); 
     try { 
      Thread.sleep(1000L); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

モジュール:

public class ExampleModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     bindInterceptor(Matchers.any(), Matchers.annotatedWith(AOPExample.class), new LoggingAOP()); 

     bind(Example.class).toProvider(ExampleProvider.class); 
    } 
} 

テストコード:

public class Test { 

    public static void main(String[] args) { 
     Injector injector = Guice.createInjector(new TestModule()); 

     ExampleProvider exampleProvider = injector.getInstance(ExampleProvider.class); 
     Example example = exampleProvider.get(); 

     example.tryMe(); 

     Example directExample = injector.getInstance(Example.class); 

     directExample.tryMe(); 

    } 
} 

テスト出力:という

start 
Building... 
end took: 3 
example working... 
start 
Building... 
end took: 0 
example working... 

お知らせ "の例では、作業は..." タイマーコードに囲まれていません。しかし、Provider.get( "Building ...")はです。

あなたの質問は:インターセプター(新しいINTERCEPTOR())がGuiceプロバイダーを通じて提供されるかどうか、その答えはいいえです。この機能に最も近いのは、モジュールのconfigureメソッドでrequestInjection()を呼び出すことです。これにより、インターセプタに適切なコードが注入されます。インターセプタから、プロバイダを使用して、起動時の遅延を引き起こすオーバーヘッドを回避できます。

は、ここで私が何を意味するかです:

モジュール:

public class TestModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(String.class).toInstance("One"); 
     bind(String.class).annotatedWith(Names.named("two")).toInstance("Two"); 

     LoggingAOP loggingAOP = new LoggingAOP(); 

     bindInterceptor(Matchers.any(), Matchers.annotatedWith(AOPExample.class), loggingAOP); 

     requestInjection(loggingAOP); 

     bind(Example.class).toProvider(ExampleProvider.class); 
    } 
} 

インターセプタ:これは、あなたの質問に答える

public class LoggingAOP implements MethodInterceptor { 

    @Inject 
    private Provider<SomethingThatTakesALongTimeToInit> provider; 

    public Object invoke(MethodInvocation invocation) throws Throwable { 
     provider.get()... 
     System.out.println("start"); 
     long start = System.currentTimeMillis(); 
     Object value = invocation.proceed(); 
     System.out.println("end took: " + (System.currentTimeMillis() - start)); 
     return value; 
    } 
} 

希望。

+1

グイスAOPの素晴らしい "Hello World"の例。 – ripper234

+0

ありがとう@ ripper234。ところで、Transfuseには私が似ている(ほぼ同じ)施設があります:http://androidtransfuse.org/documentation.html#method_interceptors –

関連する問題