2013-12-19 15 views
7

をサポートしていないのはなぜ私はGlassFishサーバーの下で悪名高いJavaEEのCDIエラーに発生:CDI Beanは、最終的な方法

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ですしかし、なぜ私は理解できません。このリンクで

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

彼らはシリアル化とは何かですが、私は、最終的なメソッドを持つクラスをシリアル化する理由は非finalメソッドを持つものよりもどんな困難にする必要があります見ることができない説明。

答えて

12

さて、プロキシオブジェクトを実装する方法はいくつかあります。しかし、プロキシがプロキシされたBeanと同じ型を持つことを期待しているため、継承(または実装可能なデマンドインターフェイス)を使用する必要がありますが、これはすべてのPOJOがBean CDI)。

つまり、注入するクラスから内部的に拡張し、その周りにプロキシコードを生成し、そのサブクラスを与えます。

このプロキシは、すべての魔法を処理して、あなたのコンテキストに合ったBeanを常に持っていることを確認しています(このBeanには、すべてのメンバー変数beansが正しいBeanを指しています)。

これで、注入するBeanのタイプを実際に受け取るのではなく、そのBeanのプロキシサブクラスを受け取ることができます。これは、最終的なメソッドやクラス、およびプライベートコンストラクタではうまく機能しません。

クラスがfinalでない場合、プロキシはこのクラスを拡張できますが、あなたの最終メソッドを簡単に上書きすることはできません。ただし、これは必要になる場合があります(たとえば、Beanがシリアル化されている場合は、プロキシがそれを逆シリアル化する必要があります)。

さらに複雑な方法があります。エージェントを介してクラスのバイトコードを操作することで、この機能を注入することができます(例えば、最終的な修飾子の削除、デフォルトのコンストラクタの挿入など)。これを継承と組み合わせることもできます。また、いくつかのJVM実装をサポートするのは自明ではありません)。これは、将来のリリースで計画されていることを示すリンクされたリソースのノートから

溶接の将来のリリースでは、おそらく使用して、この制限のための非標準的な回避策 をサポートしています非ポータブルJVM APIを: 日、IcedTeaの、マック:Unsafe.allocateInstance()(最も効率的な) IBM、JRockitの:ReflectionFactory.newConstructorForSerialization()

しかし、我々はしませんでしたこれをまだ実装することに慣れる。

+0

okがもう一度クリアされますが、もう1つの答えは正しいですが、これはより精巧です。 – dendini

10

コンテナは、注入されたクラスのプロキシオブジェクトを作成します。したがって、コンテナはクラスを使用しませんが、これらのクラスは拡張されます。 Javaでは最終クラスが拡張されないため、CDIで最終クラスを使用することはできません。

+0

私のクラスは最終的なものではありません。そのため、CDIはそれを拡張することができます。 – dendini

+2

同じプロキシクラスがメソッドをオーバーライドする問題がありますが、最終プロキシがそれらをオーバーライドできない場合は、 – Fireworks

関連する問題