簡體   English   中英

在Jersey(HK2)中按名稱動態查找服務

[英]Dynamically find service by name in Jersey (HK2)

在我的應用程序中,我需要根據一些用戶輸入獲取不同的實現。

因為我想充分利用HK2的優勢,所以我想用Jersey / HK2提供的方法解決此問題。

到目前為止,我所做的只是通過接口綁定服務,這些接口綁定到啟動時使用ApplicationConfigApplicationBinder

@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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM