Guice - 基于外部参数动态选择提供者

时间:2015-10-17 21:33:28

标签: groovy guice

在guice中,有没有办法根据一些外部参数选择特定的绑定实现

例如:

public interface Service {
  void sendMessage()
}

class EmailService implements Service {

  public EmailService() { }

  @Override 
  void sendMessage() {
   println "Sending email..."
  }
}

class SMSService implements Service {

  public EmailService() { }

  @Override 
  void sendMessage() {
   println "Sending sms..."
  }
}

class Client {

 private Service service

 @Inject
 Client(Service service) {
     this.service = service
 }

 public void send() {
     service.sendMessage()
 } 
}

public class ServiceProvider implements Provider<Service> {

  Service get() {
      return new SMSService()  //Select implementation here?
  } 

}

public class MyModule extends AbstractModule {
 @Override 
 protected void configure() {

     bind(Service.class).toProvider(ServiceProvider.class).in(Scopes.SINGLETON)

 }    
}


public static void main(String...args) {

    Injector injector = Guice.createInjector(new MyModule())
    Client c = injector.getInstance(Client.class)
    c.send()

}

在上面的例子中,我被迫选择在Provider get()方法中使用哪个提供程序。如果我想让它更具动态性,例如,根据用户偏好,有没有办法等待在运行时选择提供程序并让它注入它?

1 个答案:

答案 0 :(得分:2)

对于这些问题,guice提供了MapBinder

 public class SnacksModule extends AbstractModule {
   protected void configure() {
     MapBinder<String, Snack> mapbinder
         = MapBinder.newMapBinder(binder(), String.class, Snack.class);
     mapbinder.addBinding("twix").toInstance(new Twix());
     mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
     mapbinder.addBinding("skittles").to(Skittles.class);
   }
}

使用此绑定,现在可以注入Map:

class SnackMachine {
   @Inject
   public SnackMachine(Map<String, Snack> snacks) { ... }
}

您可以提前定义所有服务,然后通过配置值从地图中选择具体实例(或提供者)。