为什么我需要一个无 args 构造函数才能在 CDI 中使用 ApplicationScoped Bean 和构造函数注入?
我正在尝试将构造函数注入模式应用于我的CDI应用程序中的Bean,并遇到以下错误消息:
15:18:11,852 ERROR [izone.adams.webapp.error.IzoneExceptionHandler] (default task-40) org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435: Normal scoped bean class webapp.util.LoginManagerAction is not proxyable because it has no no-args constructor - <unknown javax.enterprise.inject.spi.Bean instance>.
at org.jboss.weld.bean.proxy.DefaultProxyInstantiator.validateNoargConstructor(DefaultProxyInstantiator.java:50)
实际上,为了使用构造函数注入模式,我特意使用需要参数的单个构造函数来设计我的类:
@ApplicationScoped
@Typed(LoginManagerAction.class)
public class LoginManagerAction extends UtilBasicDispatchAction {
@Inject
public LoginManagerAction( SessionManager sessionManager, JMSHealthCheckService jmsHealthCheckService) {
super();
this.sessionManager = sessionManager;
this.jmsHealthCheckService = jmsHealthCheckService;
}
...
...
}
通过查看不可复制的豆类类型的CDI规格,我发现:
3.15. 不可复制的豆类
容器使用代理来提供某些功能。某些法定豆类型不能由容器代理:
- 没有没有参数的非私有构造函数的类,
- 被宣布为最终状态的类,
- 具有非静态、最终方法的类,具有公共、受保护或默认可见性,
- 基元类型,
- 和数组类型。
如果注入点解析为 Bean,则 Bean 类型必须是可代理的:
- 需要客户端代理,或者
- 具有关联的装饰器,或
- 具有绑定拦截器。
否则,容器会自动检测问题,并将其视为部署问题。
在“正常作用域和伪作用域”一节中,它指出:
必须在@NormalScope显式声明所有正常作用域,以向容器指示需要客户端代理。
给定bean的定义,我需要有一个非私有的no-args构造函数。那么我需要一个受保护的无参数构造函数来满足CDI规范吗?我尝试过使用受保护的无参数构造函数,它似乎有效,但我不明白WELD在这种情况下是如何工作的;它在什么条件下使用无参数构造函数?为什么这是CDI的要求?@ApplicationScoped
@NormalScope
Weld 是否只使用 no-arg 来创建代理,但在实际调用底层实现时,它使用带有参数的基于 inject 的构造函数?