运行时动态CDI注入

Buh*_*ndi 4 java dependency-injection java-ee cdi

这个问题来自我一年前写的博客文章

尽管我为DAO使用了自定义CDI限定词,但我想知道是否存在一种动态注入DAO的方法。

我问的原因如下。目前,我有3个CDI限定符@HibernateDAO(对于Hibernate Session注入类型DAO),@JPADAO(对于JPA特定的DAO)和@JDBCDAO(对于纯JDBCDAO)。这就要求我必须像这样在每个具体实现上以及在注入时都指定它。

@Inject @JPADAO
private CustomerDAO customerDAO;
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法可以使我添加各种DAO,而无需更改代码,编译和部署?

我想在我的项目的下一个版本中介绍MongoDB,我在想是否可以放弃@MongoDBDAO和注入,

@Inject @MongoDBDAO
private CustomerDAO customerDAO;
Run Code Online (Sandbox Code Playgroud)

我知道CDI注入可以允许默认注入和替代注入。我希望其他开发人员可以将默认实现与另一个子类一起使用,并能够在不更改现有服务代码的情况下注入它。

这种效果:

@Inject @DAO
private CustomerDAO customerDAO;
Run Code Online (Sandbox Code Playgroud)

哪里@DAO可以有任何风格的DAO(甚至来自第三方),并且以某种方式映射@DAO以首先找到替代方法(如果找不到),则使用默认实现。

谢谢。

哦! 该解决方案必须严格使用最新的(作为撰写本文的时间)Java EE CDI规范。使用的技术:

  • RedHat JBoss Wildfly 8.2.0 Final(完全符合Java EE 7)。
  • Java 8。
  • Java EE 7 API。

我不会拒绝使用Spring Framework的解决方案,因为它可以帮助其他Spring开发人员。

mar*_*ess 5

如果要在运行时以一般方式注入Daos,我建议使用此方法。

@Qualifier
@Retention(RUNTIME)
@Target({TYPE,METHOD,FIELD,PARAMETER})
public @interface DAO{

  String value();
}

//Dont worry, CDI allows this quite often than not ;)
public class DAOImpl extends AnnotationLiteral<DAO> implements DAO {

   private final String name;
   public DAOImpl(final String name) {
     this.name = name;
   }

   @Override
   public String value() {
     return name;
   }
}
Run Code Online (Sandbox Code Playgroud)

在需要的地方。

@ApplicationScoped; //Or Whatever
public class MyDAOConsumer {

   @Inject
   @Any
   private Instance<DAOService> daoServices;

   //Just as an example where you can get the dynamic configurations for selecting daos. 
   //Even from property files, or system property.
   @Inject
   private MyDynamicConfigurationService myDanamicConfigurationService;

   public void doSomethingAtRuntime() {
     final String daoToUse = myDanamicConfigurationService.getCurrentConfiguredDaoName();
     final DAO dao = new DAOImpl(daoToUse);

     //Careful here if the DaoService does not exist, you will get UnsatisfiedException
     final DAOService daoService = daoServices.select(dao).get();
     daoService.service();
   }
}
Run Code Online (Sandbox Code Playgroud)

麻烦的是,您可以配置运行时要使用的dao。而且无需更改任何少量代码。

  • 我说`MyDynamicConfigurationService`只是获得动态配置的一种方法。它可以是系统变量,可以在系统启动或运行时设置。如何指定外部配置确实是您的选择,但是您的应用程序需要配置,不是吗? (2认同)