运行时动态CDI注入

时间:2015-04-20 10:52:08

标签: java java-ee dependency-injection cdi

这个问题将来自我一年前写的my blog post

虽然我为我的DAO使用自定义CDI限定符,但我想知道是否有动态注入DAO的方法。

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

@Inject @JPADAO
private CustomerDAO customerDAO;

是否有更好的方法可以让我添加各种风格的DAO,而无需更改代码,编译和部署?

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

@Inject @MongoDBDAO
private CustomerDAO customerDAO;

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

这种效果:

@Inject @DAO
private CustomerDAO customerDAO;

@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开发人员。

2 个答案:

答案 0 :(得分:4)

如果你想在运行时一般注入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;
   }
}

需要的地方。

@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();
   }
}

然后碰撞,您可以配置在运行时使用哪个dao而不会出汗。 并且不会改变任何一点代码。

答案 1 :(得分:3)

我会忘记自定义注释并使用生产者方法。在该方法中,您可以从xml文件或配置文件或您想要的任何方式查找要实例化的类。

在Java EE教程中查看Producer Methods