Custom Guice Scope, or a better approach?

后端 未结 4 1478
迷失自我
迷失自我 2020-12-13 14:55

Here\'s my problem:

It\'s first important to know that I\'m writing a simulation. This is a standalone application, and is single-threaded. I have essentially two

4条回答
  •  再見小時候
    2020-12-13 15:28

    With a little setup, Guice can provide two-tier scoping without a custom scope. The outer one is @Singleton, and the inner is @RequestScoped, provided by the servlet extension. This works even if you're talking about something other than a Java EE servlet container.

    Have a single, root-level injector to handle your singletons. Be sure to declare the request scope annotation in your root-level module as so:

    public class RootModule extends AbstractModule {
      @Override
      protected void configure() {
        // Tell guice about the request scope, so that we can use @RequestScoped
        bindScope(RequestScoped.class, ServletScopes.REQUEST);
      }
    }
    

    When you want to enter a sub-scope, you do this:

    private void scopeAndInject(final Object perRequestSeed) {
      try {
        ServletScopes.scopeRequest(new Callable() {
          public Void call() {
            Injector requestScoped = getRootInjector().createChildInjector(
              new AbstractModule() {
                @Override
                protected void configure() {
                  bind(Object.class).toInstance(perRequestSeed);
                }
              }
            );
    
            requestScoped.get(Something.class);
    
            return null;
          }
        }, new HashMap, Object>()).call();
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
    

    What we're doing here is using ServletScopes.scopeRequest to run the anonymous Callable inside a new request scope. The Callable then creates a child injector and adds a new binding for any per-request seed objects.

    The seeds are objects that @RequestScoped things would need but couldn't be created by Guice alone, like requests or iteration IDs. The new HashMap passed as the second argument to scopeRequest is another way to literally insert seeds into the new scope. I prefer the submodule way, since the bindings for the seeded values are always required anyway.

    The child injector is then "in" the request scope and can be used to provide @RequestScoped things.

    See this also: How to use ServletScopes.scopeRequest() and ServletScopes.continueRequest()?

提交回复
热议问题