Guice请求范围:我是否需要为servlet过滤器中的值设置Provider绑定?

时间:2013-04-10 15:39:32

标签: guice servlet-filters

我在Guice wiki文档中使用RequestScope(https://code.google.com/p/google-guice/wiki/ServletModule#Using_RequestScope)时遇到了一些问题。

我正在尝试设置一个应用程序,其中有一个请求范围的ExecutorService。我的用例是文档中的示例 - 我试图包含其他相关类的完整性。

主要区别在于我在Filter中实例化ExecutorService的实例,而不是从请求参数中提取文字值:

@Singleton
public class ExecutorServiceScopingFilter implements Filter {

    public ExecutorService getExecutor() {
        return Executors.newFixedThreadPool(10, ThreadManager.currentRequestThreadFactory());

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        ExecutorService executor = getExecutor();

        HttpServletRequest httpRequest = (HttpServletRequest) req;
        httpRequest.setAttribute(Key.get(ExecutorService.class).toString(), executor);

        chain.doFilter(req, resp);
    }

    ...
}

在我的servlet模块中,我绑定了过滤器:

public class MyServletModule extends ServletModule {
    @Override
    protected void configureServlets() {
        filter("/*").through(ExecutorServiceScopingFilter.class);
        ...
    }
}

我在我的servlet上下文监听器中正常安装模块(我已经设置了web.xml以使用guice过滤器和下面的监听器):

public class MyServletContextListener extends GuiceServletContextListener {
    @Override
    protected Injector getInjector() {
        Injector injector = Guice.createInjector(
            Stage.PRODUCTION,
            new MyServletModule(),
            new MyExampleModule(),
            ...
        );
    }
}

我在一个无范围的POJO中声明提供者:

class MyExampleImpl implements IMyExample
{
    @Inject
    protected Provider<ExecutorService> executorProvider;

    ...
}

我在模块中绑定(并且是上面我的监听器中createInjector调用的参数):

public class MyExampleModule extends AbstractModule {

   @Override
   protected void configure() {
        bind(IMyExample.class).to(MyExampleImpl.class);
   }
}

当我启动我的网络应用时,我遇到以下异常:

  

com.google.inject.CreationException:Guice创建错误:

     

1)没有绑定java.util.concurrent.ExecutorService的实现。   在找到com.google.inject.Provider时   for com.example.MyExampleImpl.executorProvider(MyExampleImpl.java:12)中的字段   在com.example.ExampleModule.configure(ExampleModule.java:23)

     

1错误

我找到了一个相关的问题,表明使用伪造的绑定(Guice: Cannot inject annotated type in Request scope)。给出的例子是:

bind(String.class)
.annotatedWith(Names.named("name"))
.toProvider(Providers.<String>of(null));

我尝试使用它来绑定ExecutorService并为提供程序获取null(因此注入器返回声明的绑定而不是使用过滤器定义的绑定)。官方文档中从未提及使用伪造的绑定。

有几个问题要尝试解决这个问题并更多地了解Guice的运作方式:

  1. 除了设置属性之外,我是否需要显式绑定(与Guice文档相比)?

  2. 如果是这样,我是否需要使用@RequestScope注释绑定任何内容?

  3. 我是否需要创建一个实现Provider的提供程序?

  4. 检查@Inject Injector对象时,我在绑定映射中看不到ExecutorService的请求范围绑定。我应该看到这种约束吗?

  5. 在运行时检查ServletScope类中的requestScopeContext线程局部变量,我确实看到了ExecutorService绑定。这表明绑定正在运行,因此我没有做某事(或做错事情)来访问它。

1 个答案:

答案 0 :(得分:5)

您不需要请求中的任何值来创建执行程序服务,因此您不需要过滤器。只需在其中一个模块中创建一个提供者方法

@Provides @RequestScoped
ExecutorService provideExecutor() {
    return Executors.newFixedThreadPool(
        10, ThreadManager.currentRequestThreadFactory());
}