2015-10-17 70 views
0

在吉斯,有没有一种方法来选择结合一些外部参数吉斯 - 基于外部参数,动态地选择供应商

如具体的实现:

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() 

} 

在上面的例子中,我m被迫选择在Provider get()方法中使用哪个提供者。如果我想让这更动态,比如说,根据用户的偏好,是否有一种方法可以在运行时选择提供者,并让guice注入它?

+1

我不会那样做注射。您可以将所有服务注入到客户端,然后定期执行if/else逻辑来选择要使用的服务。否则,您会在注入器上创建一个丑陋的依赖关系。 – zapl

+0

绑定所有的实现似乎是一个好主意。所提及的if-else逻辑的条件可以通过系统属性来传递,例如 – Opal

回答

2

对于此类问题,吉斯提供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); 
    } 
} 

有了这种结合,地图现在可以注入:

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

您可以根据预先定义的所有服务,并比通过配置的值从地图中选择具体的实例(或提供者)。