[英]Dynamically find service by name in Jersey (HK2)
在我的應用程序中,我需要根據一些用戶輸入獲取不同的實現。
因為我想充分利用HK2的優勢,所以我想用Jersey / HK2提供的方法解決此問題。
到目前為止,我所做的只是通過接口綁定服務,這些接口綁定到啟動時使用ApplicationConfig
和ApplicationBinder
:
@javax.ws.rs.ApplicationPath("api")
public class ApplicationConfig extends ResourceConfig
{
public ApplicationConfig()
{
super();
packages(true, "my.package");
register(new ApplicationBinder());
register(....);
....
}
}
public class ApplicationBinder extends AbstractBinder
{
@Override
protected void configure()
{
bind(ServletTemplateLoader.class).to(TemplateLoader.class);
bindAsContract(JobsImpl.class);
bindAsContract(JobInputAppender.class);
bindAsContract(ParamNameMapper.class);
bind(RedisJobRepository.class).to(JobRepositoryInterface.class);
....
}
但是,現在,我需要根據用戶輸入動態獲取一個實現。 有25個不同的實現都使用相同的接口。
這意味着,我不能再簡單地使用bind.to
方法。 相反,我認為我需要分別使用bindAsContract
分別注冊它們。
但是,我該如何編寫一個方法/類,以便為任何給定的輸入(來自用戶)提供正確的實現?
本質上,我需要一個看起來像這樣的方法:
public interface MyInterface {}
public class Type1Impl implements MyInterface {} // registered with `bindAsContract`
public MyInterface getImplementation(final String type_)
{
switch (type_) {
case "type1":
return // what to do here to get "my.package.Type1Impl" instance?
case "type":
....
}
}
我需要實例來自HK2,因為Impl還使用注入服務,因此我不能簡單地動態創建新實例。
我認為使用IterableProvider有更好的答案。 基本上,您可以在以下一項服務中做到這一點:
public class ImplementationGetter {
@Inject
private IterableProvider<MyInterface> interfaceProvider;
public MyInterface getImplementation(final String type_) {
return interfaceProvider.named(type_).get();
}
}
希望這可以幫助!
因此,經過數小時的搜索卻無人問津,我感到沮喪和盤旋,想着“好吧,嘗試做您能想到的最明顯的事情”。
在DI的情況下,這只是告訴容器給我我想要的東西。
事實證明,這行之有效,而且幾乎是無足輕重的……
public interface MyInterface {}
public class Type1Impl implements MyInterface {}
public class Type2Impl implements MyInterface {}
@javax.ws.rs.ApplicationPath("api")
public class ApplicationConfig extends ResourceConfig
{
public ApplicationConfig()
{
super();
packages(true, "my.package");
register(new ApplicationBinder());
}
}
public class ApplicationBinder extends AbstractBinder
{
@Override
protected void configure()
{
bindAsContract(ImplementationGetter.class);
bind(Type1Impl.class).to(MyInterface.class).named("type1");
bind(Type2Impl.class).to(MyInterface.class).named("type2");
}
}
public class ImplementationGetter {
@Inject
private ServiceLocator _locator;
public MyInterface getImplementation(final String type_)
{
switch (type_) {
case "type1":
return _locator.getService(MyInterface.class, "type1");
case "type2":
return _locator.getService(MyInterface.class, "type2");
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.