IAm*_*aja 3 java dependency-injection guice
我有一种情况,Guice正在为一些绑定工作,而对其他绑定则根本不工作.显然我错误地使用了API.
在某种程度上,这可能是因为我试图对我如何使用Guice过于"幻想".我已经创建了Modules 的继承树,我认为我已经太聪明(或愚蠢!)为了我自己的利益.
在您查看下面的代码之前,请理解我的意图,即提供可重用的Module,我可以放在JAR中并在多个项目中共享.这个可重用的抽象Module将提供所谓的"默认绑定",任何实现Module都会自动兑现.类似于AOP MethodInterceptor调用的东西Profiler,它查找带注释的方法@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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,要使用这个小库:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
这是很多代码所以我可能在将它全部输入时引入了一些拼写错误,但我向你保证这个代码编译并在运行时不会抛出任何异常.
这是发生的事情:
@Calibrated shouldBeIntercepted()方法未被截获; 但...因此,无论您认为这是多么糟糕的设计,您都不能认为Guice确实在为1个绑定(实例绑定)工作,而不是AOP方法拦截.
如果实例绑定不起作用,那么我很乐意重新审视我的设计.但是这里还有别的东西.我想知道我的继承树是否Binder以某种方式抛弃了它?
我已经验证我正在将拦截器正确绑定到注释:我创建了另一个我刚刚实现的包Module(而不是这个继承树)并使用相同的注释,相同Profiler,它工作得很好.
我曾经Injector.getAllBindings()打印出我所有MyAppModule绑定的地图作为字符串.没有什么东西可以作为这个bug的明确来源.
有任何想法吗?
拦截仅适用于Guice创建的对象(请参阅"限制" http://code.google.com/p/google-guice/wiki/AOP#Limitations).您正在使用"new"来创建DummyObj,因此无论您的模块设置多么聪明,该实例都是在外部创建的.
这是一个基于你的编码的小snipplet.(我使用你的Calibrated Annotation,但是在一个类中有其他所有内容.你应该看一下"AbstractModule".它可以节省很多你用Module-Hierarchy做的手工操作.
public class MyModule extends AbstractModule implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Intercepted@invoke!");
return methodInvocation.proceed();
}
@Override
protected void configure() {
bind(Integer.class).annotatedWith(Names.named("nonsense")).toInstance(29);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Calibrated.class), this);
}
public static void main(String... args) {
Dummy dummy = Guice.createInjector(new MyModule()).getInstance(Dummy.class);
dummy.doSomething();
System.out.println(dummy.getNonsense());
}
}
Run Code Online (Sandbox Code Playgroud)
我的假人:
public class Dummy {
@Inject
@Named("nonsense")
private int nonsense;
public int getNonsense() {
return nonsense;
}
public void setNonsense(int nonsense) {
this.nonsense = nonsense;
}
@Calibrated
public void doSomething() {
System.out.println("I have been intercepted!");
}
}
Run Code Online (Sandbox Code Playgroud)
所以你看?我从不使用"新"这个词(模块除外).我让Guice处理Dummy-Object,然后配置nonsense int的值,然后注入.
输出:
Intercepted@invoke!
I have been intercepted!
29
Run Code Online (Sandbox Code Playgroud)