我有一种情况,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)。它的理解有点棘手,请阅读下面的链接(上面的链接)。不要问我为什么这样做......这是一个很好的最佳实践,尽可能避免“新”。 –