Guice - bind different instances based on enclosing class

天涯浪子 提交于 2019-12-12 02:43:28

问题


Is it possible to bind Named instance based on the enclosing class? For ex: in the below sample, classes A and B will get DataStore instance injected. However, I need to have primary store as StoreA and secondary store as StoreB in the scope/context of class A but primary store as StoreC and secondary store as StoreD in the scope/context of class B. How can this be achieved?

class A {
   @Inject
   public A(DataStore dataStore) {
      ... 
   }
}

class B {
   @Inject
   public B(DataStore dataStore) {
      ... 
   }
}

class DataStore {
   @Inject
   public A(@Named("primary") Store primaryStore, @Named("secondary") Store store) {
      ... 
   }
}

bind(Store.class).annotatedWith(Names.named("primary")).to(StoreA.class);//for class A
bind(Store.class).annotatedWith(Names.named("secondary")).to(StoreB.class);//for class A
bind(Store.class).annotatedWith(Names.named("primary")).to(StoreC.class);//for class B
bind(Store.class).annotatedWith(Names.named("secondary")).to(StoreD.class);//for class B

回答1:


This is sometimes known as the "robot legs" problem, as if building a robot with identical legs but differing left and right feet. Each Leg to bind a Foot, but the Foot requested depends on the Leg requested. In your case, each DataStore binds to a primary and secondary Store, but which Stores depends on the DataStore requested.

A Guice-injected instance can't be bound directly based on its target (a similar feature was rejected), but as mentioned in the FAQ you can use PrivateModule to create a similar effect.

install(new PrivateModule() {
  @Override public void configure() {
    bind(Store.class).annotatedWith(Names.named("primary")).to(StoreA.class);
    bind(Store.class).annotatedWith(Names.named("secondary")).to(StoreB.class);
    expose(A.class);
  }
});
install(new PrivateModule() {
  @Override public void configure() {
    bind(Store.class).annotatedWith(Names.named("primary")).to(StoreC.class);
    bind(Store.class).annotatedWith(Names.named("secondary")).to(StoreD.class);
    expose(B.class);
  }
});

Consequently, @Named("primary") Store will not be accessible outside of A or B (or its dependencies), but that makes sense; you're never defining a general Store, but A and B each have the private bindings they need.

(Disclaimer: I didn't get a chance to test this, so it may need refinement.)



来源:https://stackoverflow.com/questions/21554841/guice-bind-different-instances-based-on-enclosing-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!