Google Guice、拦截器和 PrivateModules

Posted

技术标签:

【中文标题】Google Guice、拦截器和 PrivateModules【英文标题】:Google Guice, Interceptors and 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

【问题讨论】:

【参考方案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);

【讨论】:

不,这还不够,你还需要暴露绑定,正如我在上一篇文章中所说的。 不!你只需要绑定它。从私有模块中暴露它是不必要的(并且在某种程度上违背了私有模块的观点。)自己测试一下。

以上是关于Google Guice、拦截器和 PrivateModules的主要内容,如果未能解决你的问题,请参考以下文章

Guice 学习常量和属性的注入( Constant and Property Inject)

Google Guice 与 JSR-299 CDI / Weld

Google Guice之作用域

Google 开源的依赖注入库,比 Spring 更小更快!

史上最好用的依赖注入框架Google Guice转

Guice合成方法警告