【问题标题】:Google Guice, Interceptors and PrivateModulesGoogle Guice、拦截器和 PrivateModules
【发布时间】:2012-03-18 20:37:20
【问题描述】:

这里有新海报,希望我不要违反任何规则:)

我在 google-guice 中使用 PrivateModule,以便为同一环境提供多个 DataSource。但是我很难让 MethodInterceptor 在私有模块中工作。 下面是一个解释“问题”的简单测试用例。

一个简单的服务类是:

interface Service {
    String go();
}

class ServiceImpl implements Service {

    @Override @Transactional
    public String go() {
        return "Test Case...";
    }

}

MyModule 类将是:

class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        install(new PrivateModule() {
            @Override
            protected void configure() {
                bind(Service.class).to(ServiceImpl.class);
                bindInterceptor(
                    Matchers.any(),
                    Matchers.annotatedWith(Transactional.class),
                    new MethodInterceptor() {
                    @Override
                    public Object invoke(MethodInvocation i)
                            throws Throwable {
                        System.out.println("Intercepting: "
                                + i.getMethod().getName());
                        return i.proceed();
                    }
                });
                expose(Service.class);
            }
        });
    }

}

最后的测试用例:

public class TestCase {

    @Inject Service service;

    public TestCase() {
        Guice.createInjector(new MyModule()).injectMembers(this);
    }

    public String go() {
        return service.go();
    }

    public static void main(String[] args) {
        TestCase t = new TestCase();
        System.out.println(t.go());
    }

}

你会期望输出是:

Intercepting: go
Test Case...

但是没有发生,没有使用拦截器,只输出了antTest Case...

如果我绑定/公开ServiceImpl 而不是接口,那么它可以工作。

提前致谢, 问候, LL

【问题讨论】:

    标签: module guice private


    【解决方案1】:

    嗯...我在发布问题后不久就想通了 :)

    问题是你还需要expose() ServiceImpl 类。 所以绑定/暴露将是。

    bind(ServiceImpl.class); // ServiceImpl annotated with @Singleton
    bind(Service.class).to(ServiceImpl.class);
    expose(ServiceImpl.class);
    expose(Service.class);
    

    问候,
    LL

    【讨论】:

      【解决方案2】:

      您需要在私有模块中显式绑定 ServiceImpl。您现有代码的问题在于它从父模块继承了 ServiceImpl 的绑定。来自PrivateModule 文档,

      私有模块是使用父注入器实现的。当它可以满足它们的依赖关系时,将在根环境中创建即时绑定。此类绑定在树中的所有环境之间共享。

      添加这一行应该可以解决问题:

      bind(ServiceImpl.class);
      

      【讨论】:

      • 不,这还不够,你还需要暴露绑定,正如我在上一篇文章中所说的。
      • 不!你只需要绑定它。从私有模块中暴露它是不必要的(并且在某种程度上违背了私有模块的观点。)自己测试一下。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多