2013-12-19 45 views
7

我只是發生在臭名昭著的JavaEE CDI錯誤下GlassFish服務器:爲什麼CDI豆不支持最終方法

org.glassfish.deployment.common.DeploymentException: CDI deployment failure:Exception List with 2 exceptions: 
Exception 0 : 
org.jboss.weld.exceptions.DeploymentException: WELD-001437 Normal scoped bean class ASController is not proxyable because the type is final or it contains a final method public final void ASController.selectPath(org.primefaces.event.NodeSelectEvent) - Managed Bean [class ASController] with qualifiers [@Default @Any @Named]. 

誤差的事實相當explicative,他不喜歡裏面的最終方法CDI豆,但我不明白爲什麼。

在這個環節

http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html_single/#d0e1429

他們解釋這是什麼做的序列化,但我不明白爲什麼序列化類與final方法應該是沒有什麼難度比一個非final方法。

回答

12

那麼,有幾種方法可以實現代理對象。但是,由於您希望代理與被代理的bean具有「相同」類型,您必須使用繼承(或需求接口,然後您可以實現,但這不是每個POJO都可以成爲bean的方法CDI)。

也就是說,它們從您想要注入的類內部擴展,生成一些代理代碼併爲您提供該子類。

然後,這個代理正在處理所有的魔法,以確保你總是有一個適合你的上下文的bean(並且這個bean具有指向正好bean的所有成員變量bean)。

所以,你並沒有真正接受要注入的bean的類型,而是該bean的代理子類。這對最終的方法和類以及私有構造函數來說效果不佳。

如果這個類不是最終的,代理可以擴展這個類,但它不能輕易覆蓋你的最終方法。然而,這可能是需要的(如果你的bean被序列化,代理需要反序列化它)。

這裏有更復雜的方法。我們可以通過代理來操作你的類的字節代碼來注入這個功能(例如去掉最終的修飾符,注入一個默認的構造函數,...),甚至可以把它和繼承結合起來,但是這還沒有實現,對於幾個JVM實現也是非常重要的)。

從鏈接的資源,表明該計劃在將來的版本的說明:

將來的虛焊的版本可能會支持非標準的解決方法 這個限制,使用非便攜JVM的API: 太陽,IcedTea項目,Mac電腦:Unsafe.allocateInstance()(最有效的) IBM,JRockit的:ReflectionFactory.newConstructorForSerialization()

但我們沒有到處去實現這個呢。

+0

確定現在清除,其他答案是正確的,但是這個更加詳細。 – dendini

10

容器爲注入的類創建代理對象。所以,容器不使用你的類,但這些類繼承。 Java禁止擴展final類,所以你不能在CDI中使用final類。

+0

我的課並不是最終的,它只是有一個最終的方法,所以CDI可以擴展它。 – dendini

+2

問題相同,代理類覆蓋方法,但是如果它們的最終代理不能覆蓋它們 – Fireworks

相關問題