java - 为什么 CDI bean 不支持 final方法

标签 java jakarta-ee cdi

我刚刚在 GlassFish 服务器下遇到了臭名昭著的 JavaEE 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 中的 final方法,但我不明白为什么。

在这个链接

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

他们解释说这与序列化有关,但我不明白为什么使用 final 方法序列化类比使用非 final 方法更难。

最佳答案

好吧,有几种方法可以实现代理对象。但是由于您希望代理与被代理的 bean 具有“相同”的类型,因此您将不得不使用继承(或您随后可以实现的需求接口(interface),但这不是每个 POJO 都可以是一个 bean 的方法CDI)。

也就是说,它们从您要注入(inject)的类内部扩展,围绕它生成一些代理代码并为您提供该子类。

然后这个代理处理所有魔法以确保您始终有一个适合您的上下文的 bean(并且这个 bean 的所有成员变量 beans 都指向正确的 beans)。

因此,您实际上并没有收到要注入(inject)的 bean 的类型,而是该 bean 的代理子类。这不适用于 final方法和类以及私有(private)构造函数。

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

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

来自链接资源的注释表明这是计划在未来发布的:

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.

关于java - 为什么 CDI bean 不支持 final方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20681981/

相关文章:

java - 如何测试内部调用 AWS 服务的代码

jakarta-ee - 使用 exec-maven-plugin 运行守护进程避免 `IllegalThreadStateException`

hibernate - 在 EJB 计时器中使用 Spring Data JPA 存储库会导致 TransactionRequiredException

java - 获取泛型参数的泛型父类(super class)

java - 如何从按钮javafx获取正确的文本值

java - 虚拟玩家数量和最大玩家数量

java - 如何使用 CDI 集成将 robots.txt 添加到 Vaadin 7 应用程序?

jakarta-ee - Glassfish:如何更改 WAR 应用程序的安全领域

xml - 如何将 XML 文件用作数据库并通过 JAX-B API 访问它?

java - 注入(inject)的另一个 CDI bean 是否需要 @DependsOn?