使用Guice注入多个装饰实例 -- 在HessianServlet中混合使用Guice

4

在Guice servlet模块的configureServlets()中给出以下代码:

serve("/a").with(new Decorator(new A()));
serve("/b").with(new Decorator(new B()));
...
serve("/z").with(new Decorator(new Z()));
...

如何正确注入所有这些内容?(即在各种装饰类A、B、C中注入字段)最好/最简单的解决方案是什么?

我考虑使用命名提供者,但我宁愿不必为每个A、B、C定义新的提供者类。因此,理想的解决方案应该是通用的。


关于混合使用 Hessian 和 Guice...

为了明确问题,实际代码使用带有 Hessian 的 Web 服务。在网上搜索后,目前还没有关于这个问题的适当答案(我看过许多丑陋的黑客解决方法),而Guillaume提供的解决方案恰好符合这个精确情况。

总结原始问题:要使用 Hessian 实现 Web 服务,必须实现一个 HessianServlet,它是一个GenericServlet;然而 Guice 只能绑定 HttpServlet。因此,这个技巧就是实现一个薄包装器 HessianHttpServlet:

class HessianHttpServlet extends HttpServlet {
    public HessianHttpServlet(HessianServlet hessianServlet) {
        this.hessianServlet = hessianServlet;
    }
    @Override public void init(ServletConfig config) throws ServletException {
        hessianServlet.init(config);
    }
    @Override public void service(ServletRequest request, ServletResponse response) {                 
        hessianServlet.service(request, response);
    }
}

并且调用:

serve("/a").with(new HessianHttpServlet(new WebServiceA()));

完整的解决方案是将 WebServiceX 注入到该情况中:
void configureServlet() {
    serve("/a").with(new HessianHttpServlet(inject(new WebServiceA())));
    serve("/b").with(new HessianHttpServlet(inject(new WebServiceB())));
    ...
    serve("/z").with(new HessianHttpServlet(inject(new WebServiceZ())));
}
private HessianServlet inject(HessianServlet hessianServlet) {
    requestInjection(hessianServlet);
    return hessianServlet;
}

请原谅我的无知,Decorator 是什么?你不能只绑定 serve("/a").with(A.class) 吗?A 上的注入将自动完成。B、C、Z 也是如此。我觉得我漏掉了什么。 - Guillaume Polet
好的,装饰器的作用是在所有被装饰的类A、B、C等上添加共同的功能。如果直接将这个功能添加到A、B、C中,就会破坏使用装饰器的优势。此外,装饰器可以动态地改变;这里我只举了一个简单的例子,只有一个装饰器。 - Laurent Grégoire
2个回答

3
您可以在每个装饰器上使用requestInjection(Object instance)

在我的情况下,我只需要注入已装饰的实例,因此调用serve("/a").with(new Decorator(injected(new A())))即可完成操作,其中injected()是一个辅助函数,仅调用requestInjection()并返回实例。但不知为何,我写这个代码时心里感觉不太舒服,有一种这样使用DI可能有些不当的印象。 - Laurent Grégoire
我想我理解你的感受。你希望有一种方法来表达serve("/a*").with(Decorator.class).using(A.class);(语法不正确,但它可以表达你想要的)。不幸的是,我的Guice知识并没有达到那个程度。 - Guillaume Polet

1
我创建了一个小型的开源项目,使得Hessian和Guice的集成变得容易。您可以使用基于注解的配置,就像这样: WebService:
@HessianWebService
public class UserServiceImpl implements UserService {
    ...
}

Guice配置:
public class WebServiceGuiceServletContextListener extends GuiceServletContextListener {
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(
                /* your guice modules */
                new HessianWebServicesModule("your web service implementations package")
        );
    }
}

或者使用 EDSL 手动方式:
public class WebServiceGuiceServletContextListener extends GuiceServletContextListener {
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(
                /* your guice modules */
                new HessianWebServicesModule(){
                    @Override
                    protected void configureHessianWebServices() {
                        serveHessianWebService(UserService.class).usingUrl("/Users");
                    }
                }
        );
    }
}

更多信息、配置选项和完整示例可在此处找到:https://bitbucket.org/richard_hauswald/hessian-guice/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接