Why CDI beans don't support final methods

懵懂的女人 提交于 2019-12-08 19:27:02

问题


I just incurred in the infamous JavaEE CDI error under GlassFish server:

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].

the error is quite explicative in the fact that he doesn't like final methods inside a CDI bean, however I can't grasp why.

At this link

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

they explain it is something to do with serialization but I can't see why serializing a class with a final method should be any harder than one with non final methods.


回答1:


Well, there is several ways in which you can implement a proxy object. But since you expect the proxy to have the "same" type as the proxied bean, you'll have to use inheritance (or demand interfaces which you then could implement, but this would not be an approach where every POJO could be a bean for CDI).

That is, they internally extend from the class you want to inject, generate some proxy code around that and give you that sub class.

This proxy then is handling all the magic to make sure you always have a bean fitting your context (and this bean has all the members variable beans pointing to the just right beans).

So you are not really receiving the type of the bean you want to inject, but a proxy subclass of that bean. This does not work very well with final methods and classes and private constructors.

If the class is not final, the proxy can extend this class, it however cannot easily overwrite the final method of yours. This however may be needed (if e.g your bean is serialized, the proxy needs to deserialize it).

There is, more complicated ways, around that. One could inject this functionality by manipulating the byte code of your class via an agent (e.g removing the final modifiers, inject a default constructor, ...) and maybe even mix this with inheritance, but this is just not implemented, yet (and also non trivial to support over several JVM implementations).

From the linked resource a note indicating that this is planned for a future release:

Note

A future release of Weld will likely support a non-standard workaround for this limitation, using non-portable JVM APIs: Sun, IcedTea, Mac: Unsafe.allocateInstance() (The most efficient) IBM, JRockit: ReflectionFactory.newConstructorForSerialization()

But we didn't get around to implementing this yet.




回答2:


Container create proxy object for injected classes. So, container doesn't use your classes, but those classes extends. Java prohibit extends final classes, so you cannot use final classes in CDI.



来源:https://stackoverflow.com/questions/20681981/why-cdi-beans-dont-support-final-methods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!