为什么CDI bean不支持最终方法 [英] Why CDI beans don't support final methods

查看:168
本文介绍了为什么CDI bean不支持最终方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在GlassFish服务器下的臭名昭着的JavaEE CDI错误中招致:

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

错误很明显,因为他不喜欢CDI bean中的final方法,但我无法理解原因。

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.

在此链接

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.

推荐答案

嗯,有几种方法可以实现代理对象。但是,由于您希望代理与代理bean具有相同类型,因此您必须使用继承(或者您可以实现的需求接口,但这不是每个POJO都可以作为bean的方法) CDI)。

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.

然后这个代理正在处理所有的魔法,以确保你总是有一个适合你的上下文的bean(这个bean的所有成员变量bean都指向恰到好处的bean)。

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

因此,您并没有真正接收要注入的bean的类型,而是该bean的代理子类。这对最终方法和类以及私有构造函数不起作用。

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.

如果类不是final,代理可以扩展这个类,但它不能轻易覆盖你的最终方法。然而,这可能是需要的(例如,如果您的bean被序列化,代理需要对其进行反序列化)。

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

有更复杂的方法。可以通过代理操作类的字节代码来注入此功能(例如删除最终修饰符,注入默认构造函数,......)甚至可以将它与继承混合使用,但这只是没有实现,但是(和支持多个JVM实现也是非常重要的。)

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

未来的Weld版本可能会支持非标准的解决方案
来解决此限制,使用不可移植的JVM API:
Sun,IcedTea,Mac:Unsafe.allocateInstance()(效率最高)
IBM,JRockit:ReflectionFactory.newConstructorForSerialization()

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.

这篇关于为什么CDI bean不支持最终方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆