我有一種情況,Guice正在爲某些綁定工作,而不是爲其他人工作。很明顯,我錯誤地使用了API。Guice不會攔截帶註釋的方法
部分原因可能是因爲我試圖讓我對Guice的使用過於「迷戀」。我創建了一個Module
的繼承樹,我認爲我爲了自己的利益已經太聰明瞭(或愚蠢!)。
你看看下面的代碼之前,就請理解我的用意,這是提供一個可重用的Module
,我可以在一個JAR放置並在多個項目共享。這個抽象的,可重用的Module
將提供所謂的「默認綁定」,任何實現的Module
都會自動頒發。事情是這樣叫Profiler
的AOP MethodInterceptor
,它看起來與@Calibrated
註解的方法,並自動記錄多長時間需要爲這個方法來執行,等等。
注意以下事項:
@Target({ ElementType.METHOD })
@RetentionPolicy(RetentionPolicy.RUNTIME)
@BindingAnnotation
public @interface Calibrated{}
public class Profiler implement MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// Eventually it will calculate and log the amount of time
// it takes an intercepted method to execute, hence "Profiler".
System.out.println("Intercepted!");
return arg0.proceed();
}
}
public abstract class BaseModule implements Module {
private Binder binder;
public BaseModule() {
super();
}
public abstract void bindDependencies();
@Override
public void configure(Binder bind) {
// Save the binder Guice passes so our subclasses can reuse it.
setBinder(bind);
// TODO: For now do nothing, down the road add some
// "default bindings" here.
// Now let subclasses define their own bindings.
bindDependencies();
}
// getter and setter for "binder" field
// ...
}
public abstract class AbstractAppModule extends BaseModule {
/* Guice Injector. */
private Injector injector;
// Some other fields (unimportant for this code snippet)
public AbstractAppModule() {
super();
}
// getters and setters for all fields
// ...
public Object inject(Class<?> classKey) {
if(injector == null)
injector = Guice.createInjector(this);
return injector.getInstance(classKey);
}
}
因此,要使用這個小型圖書館:
public class DummyObj {
private int nonsenseInteger = -1;
// getter & setter for nonsenseInteger
@Calibrated
public void shouldBeIntercepted() {
System.out.println("I have been intercepted.");
}
}
public class MyAppModule extends AbstractAppModule {
private Profiler profiler;
// getter and setter for profiler
@Override
public void bindDependencies() {
DummyObj dummy = new DummyObj();
dummy.setNonsenseInteger(29);
// When asked for a DummyObj.class, return this instance.
getBinder().bind(DummyObj.class).toInstance(dummy);
// When a method is @Calibrated, intercept it with the given profiler.
getBinder().bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Calibrated.class),
profiler);
}
}
public class TestGuice {
public static void main(String[] args) {
Profiler profiler = new Profiler();
MyAppModule mod = new MyAppModule();
mod.setProfiler(profiler);
// Should return the bounded instance.
DummyObj dummy = (DummyObj.class)mod.inject(DummyObj.class);
// Should be intercepted...
dummy.shouldBeIntercepted();
System.out.println(dummy.getNonsenseInteger());
}
}
這是一個很大的代碼,以便在鍵入時,這一切也許是我介紹了幾個錯別字,但我向你保證,這個代碼編譯和運行時沒有拋出異常。
這裏發生了什麼:
- 的
@Calibrated shouldBeIntercepted()
方法是不攔截;但... - 控制檯輸出顯示虛擬的無意義整數爲... 29 !!!!
所以,無論多麼貧窮設計你可能認爲這是,你不能說吉斯確實是1結合工作(實例綁定),而不是AOP方法攔截。
如果實例綁定不起作用,那麼我會很高興地重新訪問我的設計。但其他事情正在發生。我想知道我的繼承樹是否拋棄了Binder
?
而且我已經驗證了我正確地綁定攔截器的註解:我創建了另一個包,我只是執行(而不是這個繼承樹)Module
並使用相同的註解,同樣Profiler
,並且它完美精細。
我用Injector.getAllBindings()
打印出我的所有MyAppModule
的綁定作爲字符串的地圖。沒有任何東西可以作爲這個錯誤的明確來源。
任何想法?
所以是你在說什麼:(1)因爲我使用'new',我實際上沒有獲得通過吉斯的'Dummy';和(2)因爲我然後從非Guice注入的'Dummy'運行'Calibrated'方法,那Guice沒有攔截它?這是主意嗎?如果是這樣,那就很有道理。如果不是,請你澄清一下嗎?再次感謝您的幫助和這麼好的回答(+1)! – IAmYourFaja
您的DummyObj實例不是由guice創建的。它由你創建並且在模塊中綁定,所以你總是會得到相同的預創建的實例。所以基本上:是的,我說的是(1)和(2)。它的理解有點棘手,請閱讀下面的鏈接(上面的鏈接)。不要問我爲什麼這樣做......這是一個很好的最佳實踐,儘可能避免「新」。 –