簡體   English   中英

CDI / WELD 構造函數注入最佳實踐

[英]CDI / WELD Constructor injection best practices

在“單體”Jakarta-EE 8 應用程序中,我們希望將 JSF 與 CDI 結合使用。 下圖給出了視圖和類如何相互依賴的示例:

JSF-View -> ViewController -> BeanA --> BeanA1
                                    \-> BeanA2
                                

在這種情況下, ViewController@Named + @ViewScoped ,所有其他 bean( BeanABeanA1BeanA2 )都是@SessionScoped 我們希望使用構造函數注入作為最佳實踐。 基於此,我們的類看起來像這樣:

@Named
@ViewScoped
public class ViewController implements Serializable {

    private final BeanA bean;
    
    @Inject
    public ViewController(final BeanA bean) {
        this.bean = bean;
    }
}

@SessionScoped
public class BeanA implements Serializable {

    private final BeanA1 bean1;
    
    private final BeanA2 bean2;
    
    @Inject
    public BeanA(final BeanA1 bean1, final BeanA2 bean2) {
        this.bean1 = bean1;
        this.bean2 = bean2;
    }
}

將其作為 WAR 部署到 Wildfly 20 時,我們以以下錯誤/異常結束:

"BeanA is not proxyable because it has no no-args constructor".

由於我們不打算在集群中運行服務器,我不明白為什么我們需要非參數構造函數(根本不需要序列化)。

添加META-INF/org.jboss.weld.enableUnsafeProxies文件解決了問題,我們可以部署和運行應用程序而不會出現任何錯誤。 我問自己這是一個好習慣還是我們錯過了什么?

首先,最快的答案是:在正常范圍內的任何 bean 都必須有一個非私有的、零參數的構造函數。 此外,此類類不得為final且不得具有非私有的、虛擬的final方法。 @SessionScoped是一個正常范圍

如果您點擊鏈接,您將看到 CDI 規范中的原因不是(可能主要是)因為序列化,而是因為代理

您所指的屬性是Weld 特定的功能 如果您知道將繼續使用 Weld 進行 CDI 實現,那么您當然可以繼續使用此屬性,但嚴格來說,您的 CDI 應用程序現在是不可移植的。 這對您來說可能重要也可能無關緊要。

我發現的這個問題最實用、最現實的解決方案是定義一個包私有零參數構造函數,它是@Deprecated ,將字段設置為null

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM