gpt4 book ai didi

java - Guice 不会拦截带注释的方法

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:31:17 29 4
gpt4 key购买 nike

我遇到的情况是 Guice 正在为某些绑定(bind)工作,而根本不为其他绑定(bind)工作。显然我使用的 API 不正确。

部分原因可能是因为我试图对自己使用 Guice 的方式过于“花哨”。我已经创建了一个 Module 的继承树,但我认为我太聪明了(或者太愚蠢了!),这对我不利。

在您查看下面的代码之前,请理解我的意图,即提供一个可重用的模块,我可以将其放入 JAR 中并在多个项目中共享.这个抽象的、可重用的 Module 将提供所谓的“默认绑定(bind)”,任何实现 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!!!!

因此,无论您认为这是多么糟糕的设计,您都不能争辩说 Guice 确实适用于 1 绑定(bind)(实例绑定(bind)),而不适用于 AOP 方法拦截。

如果实例绑定(bind)不起作用,那么我会很乐意重新审视我的设计。但是这里还发生了其他事情。我想知道我的继承树是否以某种方式丢弃了 Binder

而且我已经验证我将拦截器正确地绑定(bind)到注释:我创建了另一个包,我只是实现了 Module(而不是这个继承树)并使用相同的注释,相同的Profiler,它工作得很好。

我使用 Injector.getAllBindings() 将我所有 MyAppModule 的绑定(bind)映射打印为字符串。没有什么是这个错误的明确来源。

最佳答案

拦截仅适用于 Guice 创建的对象(参见“限制”http://code.google.com/p/google-guice/wiki/AOP#Limitations)。您正在使用“new”来创建 DummyObj,因此无论您的模块设置得多么巧妙,实例都是在 guice 之外创建的。

这是基于您的编码的一个小片段。 (我使用了您的校准注释,但在一个类中包含了其他所有内容。您应该看看“AbstractModule”。它节省了您使用模块层次结构所做的大量手动工作。

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());
}
}

还有我的假人:

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!");
}
}

所以你看到了吗?我从不使用"new"这个词(除了模块....)。我让 Guice 处理 Dummy-Object 并为无意义的 int 配置值,然后注入(inject)。

输出:

Intercepted@invoke!
I have been intercepted!
29

关于java - Guice 不会拦截带注释的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10702481/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com