【问题标题】:Inject Service dynamically from Database parameter CDI从数据库参数 CDI 动态注入服务
【发布时间】:2020-01-14 12:00:10
【问题描述】:

我有一些服务实现了相同的接口。我想根据数据库中的参数动态使用服务。

我想使用 CDI 注释,但如果不可能,请告诉我如何实现它?一个工厂 ?

我们有几个与服务相关的提供者,并遵循数据库中的规则,我们将使用服务或其他

Service1 implements IService1, IGeneralService{

public void run(){...};}

Service2 implements IService2, IGeneralService{

public void run(){...};}

然后我会根据国家或其他国家/地区的数据库参数使用它。

public class Test{
    @IGeneralService service;

public void getRunMethod(String numberService){
      service.run() (here it run the right service)
}
}

类似的东西。任何想法 ?

【问题讨论】:

标签: java dependency-injection cdi


【解决方案1】:

是的,您的测试类看起来很像工厂。继续你所拥有的,它可能看起来像这样:

public class Test{
    @IGeneralService service0;
    @IGeneralService service1;

    public void getRunMethod(String numberService){
      if(numberService == '0')
          service0.run() 
      if(numberService == '1')
          service1.run() 
    }
}

您可以更加了解如何管理该服务列表(地图、列表)。但是这里的缺点可能是您必须显式地注入每个服务。

你也可以走另一条路,将 BeanManager 注入你的工厂:

public class Test{
    @Inject
    BeanManager bm;

    public void getRunMethod(String numberService){
        IGeneralService svc = (IGeneralService) bm.getBeans(numberService).iterator().next();
        svc.run();
    }
}

现在您不需要显式注入每个服务。

这是您可以在这里使用的两种基本方法。哪个更好取决于您的用例。

【讨论】:

  • 第二种方法看起来不错,我想自动将数据库值 ENUM 链接到 BEAN 名称 ^^ 谢谢
  • 用这个方法我有一个例外:org.jboss.weld.bean.ManagedBean 不能转换为 IGeneralService
  • 我的回答很笼统。您必须找出为什么您的服务包含在其中。
【解决方案2】:

有一种更清洁的方法。

@interface Provider {
    String value(); // provider id retrieved from the db
}

class ProviderImpl extends AnnotationLiteral<Provider> implements Provider {
    String providerId;
    ProviderImpl(String providerId) { this.providerId = providerId;}
}

然后为您的每个服务提供商,适当地注释它们:

@Provider("provider-1")
class ProviderOneImpl implements ServiceProvider {}

那么用法是这样的:

class ServiceProcessor {
   @Any
   @Inject
   Instance<ServiceProvider> serviceProviders;

   void doSomethingAwesome() {
      String enabledProvider = getCurrentProviderId();
      Provider provider = new ProviderImp(enabledProvider);
      ServiceProvider serviceProvider = serviceProviders.select(provider).get();
      serviceProvider.run();
   }
}

【讨论】:

    【解决方案3】:

    【讨论】:

    • 喜欢建议为重复?那么就不需要创建这个作为答案,但也可以投票让它成为一个副本并将它作为评论发布;-)
    【解决方案4】:

    你可以注入de接口:

    @Inject
    @Any
    private Instance <Payment> paymentsLazy;
    

    在你的方法之后你可以选择实现

    Payment object = paymentsLazy.select(Cash.class).get ();
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 2015-06-27
      • 2020-03-30
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      相关资源
      最近更新 更多