How to implement the “robot legs” use case with Google Guice?

后端 未结 1 521
青春惊慌失措
青春惊慌失措 2020-12-06 22:45

I\'m learning Google Guice. Do you know how to implement the \"robot legs\" problem? Let me explain this with an example.

Let\'s say that I have some class called

相关标签:
1条回答
  • 2020-12-06 23:15

    As documented in the Guice Wiki, you need to install two PrivateModules, each of which exposes a Service with the right annotation for you.

    public class MyModule extends AbstractModule {
      @Override
      protected void configure() {
        install(new PrivateModule() {
          @Override public void configure() {
            // Bind Source to SourceDatabase.
            bind(Source.class).to(SourceDatabase.class);
            // Bind @Named("database") Service to Service.
            bind(Service.class).annotatedWith(Names.named("database"))
                .to(Service.class);
            // Now expose @Named("database") Service without exposing
            // either of the other two conflicting bindings.
            expose(Service.class).annotatedWith(Names.named("database"));
          }
        });
        install(new PrivateModule() {
          @Override public void configure() {
            // Same as above.
            bind(Source.class).to(SourceFileSystem.class);
            bind(Service.class).annotatedWith(Names.named("file-system"))
                .to(Service.class);
            expose(Service.class).annotatedWith(Names.named("file-system"));
          }
        });
      }
    }
    

    If the modules were not PrivateModule instances, those bindings to Source and Service would conflict with one another. However, instead, each binding inherits all the public bindings from the Injector but only exposes the @Named(...) Service to the outside world. This way the same Service implementation can inject the same non-annotated Source but have it return different fully-injected types.

    Also note that you will not be able to ask for a Source or Service (without an annotation) outside of the PrivateModules, because you haven't established a binding in any non-private Module. This should be expected: The PrivateModule bindings shouldn't conflict with any public bindings, and without entering through one of the PrivateModule's exposed bindings, Guice won't know which Source or Service to return.

    Finally, given that Module instances can take constructor parameters, it may be a good idea to extract the two anonymous inner PrivateModules into a named equivalent:

    public class MyModule extends AbstractModule {
      @Override
      protected void configure() {
        install(new SourcePrivateModule(SourceDatabase.class, "database"));
        install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
      }
    }
    
    0 讨论(0)
提交回复
热议问题