2011-12-06 63 views
11

有沒有辦法將方法攔截器綁定到提供者而不是實例?如何將方法攔截器綁定到提供者?

例如我使用下面的代碼來綁定攔截器如何將INTERCEPTOR綁定到提供者然後綁定到註釋上?

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

你想攔截什麼? get()方法或者一些setter方法? –

+0

那麼理想的任何方法,我們有一個性能監視系統,攔截方法調用和時間他們的執行等。我想懶惰地初始化攔截器。 –

回答

18

吉斯不允許AOP就不會被吉斯內置實例:Guice AOP Limitations

「實例必須由吉斯通過創建@注入註解或無參數的構造」

這意味着,使用提供者創建的實例不會是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 ...」)是。

如果您的問題是:是否可以通過Guice Provider提供攔截器(新的INTERCEPTOR()),答案是否定的。最接近此功能的是調用模塊configure方法中的requestInjection()。這將爲您的Interceptor注入適當的代碼。從攔截器中,您可以使用提供程序來避免任何會導致啓動過程中緩慢的開銷。

這裏就是我的意思是:

模塊:

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

偉大的「Hello World」例子給Guice AOP。 – ripper234

+0

謝謝@ ripper234。順便說一下,我們在Transfuse中有類似(幾乎相同)的工具,這是我一直在研究的一個項目:http://androidtransfuse.org/documentation.html#method_interceptors –