2017-04-04 55 views
1

我是DI新手,但突然間需要在我的EJB應用程序中使用它,所以我嘗試重新創建它。依賴注入和容器類(java-ee 7)

該方法包括具有2個字段 - 2個實現的容器類。它根據參數與一個或兩個實現協同工作。該容器是在單例的方法調用中創建的,但被其他ejb bean使用。

在這裏我需要幫助 - 如何使SecurityContainer類與其他CDI託管類(ejb beans)正常工作或成爲CDI管理自己?

我正在給一箇舊的(非CDI)代碼,它是如何工作的。讀取參數和實例容器:

@Singleton 
public class MySingleton { 
    private static final MySingleton instance = new MySingleton(); 
    private volatile SecurityHelper securityHelper; // container 
    public void setSecurityHelper(SecurityHelper secHelper){ securityHelper=secHelper; } 
    public SecurityHelper getSecurityHelper(){ return securityHelper; }  
    /* now it has some @Inject....*/  

    public void start(String passwordP, String passwordH) 
      ..... 
     // application work with one or two implementations of security 
     if ("P".equals(DbParams.getServerSecurityFlag())) 
      instance.setSecurityHelper(new SecurityContainer(new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
           null));    
     else 
      instance.setSecurityHelper(new SecurityContainer(new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
           new SecurityHelperImplH(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()))); 
     securityHelper.createSecurity(passwordP, passwordH); 

下面是容器類:

public class SecurityContainer implements SecurityHelper { 
    private SecurityHelper secPrg; 
    private SecurityHelper secHard; 
    public SecurityContainer(SecurityHelper secPrg, SecurityHelper secHard){ 
     this.secPrg=secPrg; 
     this.secHard=secHard; 
    } 

具體實現目前有注入DbWorker和ResponseBuilder EJB豆。 SecurityHelperImplH看起來一樣。

public class SecurityHelperImplP implements SecurityHelper { 
    private SecurityPrg securityPrg = null; 

    private DbWorker ora;   // now they are CDI managed 
    private ResponseBuilder builder; 

    public SecurityHelperImplP(DbWorker dbworker, ResponseBuilder bld){ 
     this.ora = dbworker; 
     this.builder = bld; 
    } 

我相信我需要預選賽,也許製片人,但不能點

回答

0

連接到它的外觀,你去任何一種方式 - 生產商或預選賽。兩者都需要一些重構,對我來說,似乎製片人是一種更流暢的方式。 它將允許您檢查參數並根據您的需要定製生產者對象(SecurityContainer)。

首先,你需要SecurityContainer領域是一個注射點,所以加@Inject

@Inject 
private volatile SecurityHelper securityHelper; // container 

注:請記住刪除setter方法,使用CDI的時候,你不希望/需要它。

現在我們如何生產它。你的工作基本上已經完成了!所有你需要的是讓它成爲一個製作者,設置正確的返回類型,並確保你獲得了參數。所以,有步驟:

1)製片方法參數

生產者方法的所有prameters被自動認爲是另一個可注射的來源。例如。你一定能夠@Inject String passwordP)。哎呀,這不會馬上工作,我不知道你是如何完全檢索這些參數的。

2)如何生產方法操作

這是一個方法調用CDI每次它需要創建一個實例。所以你必須在範圍內打定主意SecurityHelper。由於這是在@Singleton的啓動方法中設置的一次,我想這是在運行時不會更改的東西。在這種情況下,您可能需要@ApplicationScoped

3)如何看起來呢?

這是應該做你想要什麼代碼,假設我沒有誤會了吧:

@Produces // telling CDI this is how it is supposed to create instances of this type 
@ApplicationScoped // what scope does the produced bean have? 
public SecurityHelper produceSecHelper() { 
    // TODO add logic to retrieve these params! 
    String passwordP; 
    String passwordH; 

    SecurityHelper result; 
    // application work with one or two implementations of security 
    if ("P".equals(DbParams.getServerSecurityFlag()){ 
     result = new SecurityContainer(new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
           null); 
    } else { 
     result = new SecurityContainer(new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
           new SecurityHelperImplH(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance())); 
    } 
    result.createSecurity(passwordP, passwordH); 
    return result; 
} 

注:CDI將調用根據自身此方法。您不應該手動進行此操作,即使您這樣做,也不會被CDI識別。

+0

你認爲這個製片人在哪裏? 現在我離開了SecurityContainer,因爲它是。 MySingleton現在是CDI託管的,其他託管的bean使用mySingleton getSecurityHelper()中的securityContainer。 – Buch

+0

無關緊要,只要生產者駐留在另一個CDI bean中(以便CDI能夠找到它)。從CDI 1.2規範 - 「生產者方法必須是託管bean類或會話bean類的默認訪問,公共,受保護或私有的非抽象方法。 「所以我說,把它放在方便你的地方。 – Siliarus

+0

我應該將SecurityHelperImplP和SecurityHelperImplH作爲參數傳遞給Producer嗎?我試圖通過限定符來傳遞它們,但得到編譯錯誤 – Buch