2013-12-19 5 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]. 

ошибка вполне поясняющая в том, что он не любит окончательные методы внутри CDI bean, однако я не могу понять почему.

В этой связи

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

они объясняют это что-то делать с сериализацией, но я не могу понять, почему сериализаций класса с окончательным методом должен быть тяжелее, чем один с не конечными методами.

ответ

12

Ну, существует несколько способов реализации прокси-объекта. Но поскольку вы ожидаете, что прокси-сервер будет иметь «тот же» тип, что и прокси-сервер, вам придется использовать наследование (или интерфейсы спроса, которые вы тогда могли бы реализовать, но это не будет подход, когда каждый POJO может быть компонентом для CDI).

То есть, они внутренне простираются от класса, который вы хотите внедрить, генерируете некоторый прокси-код вокруг этого и дают вам этот подкласс.

Этот прокси-сервер обрабатывает всю магию, чтобы убедиться, что у вас всегда есть компонент, соответствующий вашему контексту (и этот компонент имеет все переменные bean-элементы, указывающие на правые бобовые).

Таким образом, вы действительно не получаете тип компонента, который хотите вставить, но прокси-подкласс этого компонента. Это не очень хорошо работает с конечными методами и классами и частными конструкторами.

Если класс не является окончательным, прокси-сервер может расширить этот класс, однако он не может легко переписать окончательный метод. Это может потребоваться (если, например, ваш бин сериализуется, прокси-сервер должен десериализовать его).

С этим связаны более сложные способы. Можно вводить эту функциональность, манипулируя байтовым кодом вашего класса с помощью агента (например, удаляя финальные модификаторы, вставляя конструктор по умолчанию ...) и, возможно, даже смешивая это с наследованием, но это еще только не реализовано (и также нетривиальны для поддержки нескольких реализаций JVM).

Из связанного ресурса примечание, указывающее, что планируется в будущем выпуске:

Примечание

Будущий релиз Weld, скорее всего, поддерживать нестандартную обходной путь это ограничение, используя непортабельный JVM APIs: ВС, IcedTea, Mac: Unsafe.allocateInstance() (наиболее эффективный) IBM, JRockit: ReflectionFactory.newConstructorForSerialization()

Но мы не сделали обойти это, чтобы реализовать это.

+0

ОК теперь понятно, другой ответ был верным, но этот более сложный. – dendini

10

Контейнер создает прокси-объект для введенных классов. Таким образом, контейнер не использует ваши классы, но эти классы расширяются. Запрет Java расширяет конечные классы, поэтому вы не можете использовать финальные классы в CDI.

+0

Мой класс не является окончательным, он просто имеет окончательный метод, поэтому CDI может его расширить. – dendini

+2

Неполадка же, методы переопределения классов прокси, но если они окончательный прокси не могут переопределить их – Fireworks

Смежные вопросы