这个问题将来自我一年前写的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规范。使用的技术:
我不会下载使用Spring Framework的解决方案,因为它可以帮助其他Spring开发人员。
答案 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。