2015-04-20 110 views
3

這個問題將引用從my blog post我寫了一年前。動態CDI注入在運行時

雖然我使用自定義CDI限定符爲我的DAO,我想知道是否有一種方法動態注入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中的注入可以讓默認和交替注入。我希望其他開發人員可以使用其他子類的默認實現進行覆蓋,並且可以在不更改現有服務代碼的情況下注入它。

東西的這種效果:

@Inject @DAO 
private CustomerDAO customerDAO; 

哪裏@DAO可以任何的任何味道(甚至第三方),並以某種方式映射@DAO先找到替代DAO,如果沒有找到,使用默認的實現。

謝謝。

哦!此解決方案必須嚴格執行與最新(作爲當前寫作時間)Java EE CDI規範一起工作。使用的技術:

  • RedHat JBoss Wildfly 8.2.0最終版(完全兼容Java EE 7)。
  • Java 8.
  • Java EE 7 API。

我不會downvote使用Spring框架的解決方案,因爲它可以幫助其他Spring開發人員。

+3

你檢查了嗎? http://docs.oracle.com/javaee/7/tutorial/cdi-adv002.htm#GJSDF – assylias

+0

哎,謝謝!我怎麼錯過了這個?讓我快速研究一下。 :-) –

回答

2

如果你想在運行時一般地注入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

第三方開發人員如何使用這種方法來整合他們的服務/ DAO?他們必須通過在自定義的MyDynamicConfigurationService中添加他們的DAO並編譯來更改代碼。必須有一個更簡單的方法,它們不涉及根代碼,但有自定義代碼,可以通過XML配置或註釋進行註冊,並且CDI容器知道如何注入它,而不會出現任何問題。 –

+2

我說''''MyDynamicConfigurationService'''只是一種獲取動態配置的方法。它可能是一個系統變量,可以在系統啓動時或運行時設置。如何指定外部配置實際上是您的選擇,但您的應用程序需要配置,不是嗎? – maress

+0

DAOServic類應該實現DAO接口嗎? –

3

我會忘記自定義註釋並使用生產者方法。在該方法中,您可以查找要從xml文件或配置文件實例化的類,或者您想要執行的任何方式。

在Java EE教程中查看Producer Methods

+0

我想避免自定義配置,因爲我將不得不通過教程和培訓將其介紹給第三方開發人員。我希望使用現有的CDI技術。 –

+0

使用new實例化類時,不會將CDI注入到生成類中。如果你這樣做,如下面的女士建議,這將起作用。 –

+1

這就是生產者的方法。他們讓您創建CDI然後管理的對象。 – mamboking