[英]CDI / WELD Constructor injection best practices
在“單體”Jakarta-EE 8 應用程序中,我們希望將 JSF 與 CDI 結合使用。 下圖給出了視圖和類如何相互依賴的示例:
JSF-View -> ViewController -> BeanA --> BeanA1
\-> BeanA2
在這種情況下, ViewController
是@Named
+ @ViewScoped
,所有其他 bean( BeanA
、 BeanA1
、 BeanA2
)都是@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.