2015-10-17 100 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) { ... } 
} 

您可以根據預先定義的所有服務,並比通過配置的值從地圖中選擇具體的實例(或提供者)。