我的应用程序正在部署到IBM WebSphere上。我有一个简单的服务,我想知道在这种情况下依赖注入的工作原理。
// stateless EJB
@Stateless
public class UserService {
private UserDAO userDAO;
// btw, UserDAO is stateless EJB as well
@Inject
public UserService(UserDAO userDAO) {
this.userDAO = userDAO;
}
// biz methods ...
}
它失败并出现以下错误:
[错误] CWWKZ0002E:启动计算机时发生异常 应用程序my-app。异常消息为: com.ibm.ws.container.service.state.StateChangeException: com.ibm.ws.cdi.CDIException: com.ibm.wsspi.injectionengine.InjectionException: com.ibm.ejs.container.EJBConfigurationException:EJB类 com.demo.app.UserService必须具有一个 不带参数的公共构造函数
我记得EJB规范中有一句话:the class must have a public constructor that takes no parameters
,对我来说, bean实例首先由容器实例化,然后进行依赖注入。 / p>
另一方面,我在WELD文档中发现了这一点:
首先,容器调用bean构造函数(默认 构造函数或带注释的@Inject),以获取的实例 豆。
我有点困惑,为什么无法实例化我的EJB。
当我们有构造函数注入点时,如何创建EJB实例并注入依赖项?
有什么想法吗? :)
答案 0 :(得分:3)
EJB会话Bean的创建是由EJB容器完成的,但是它可以选择使用CDI提供EE资源注入,但是EJB解析则委托给了容器
https://docs.jboss.org/weld/reference/2.1.0.Final/en-US/html/ri-spi.html说:
或者,集成商可以选择使用CDI提供EE 资源注入。在这种情况下,EE_INJECT环境应为 使用,集成商应实现第A.1.4节“ EJB 服务”,第A.1.7节“资源服务”和第A.1.5节“ JPA” 服务”。 ....
焊接将资源注入点注册到 EjbInjectionServices,JpaInjectionServices,ResourceInjectionServices 和JaxwsInjectionServices实施(在引导程序中)。 这允许在以下位置执行资源注入点的验证 启动时间而不是运行时间
如果您对CDI和EJB的集成方式感兴趣。您可以看一下weld-EJB模块和weld-integration的代码(glassfish代码)
答案 1 :(得分:3)
所以发生的事情是您不满足初始化EJB bean的要求。
CDI规范对构造函数有一些限制-无参数或带有@Inject
的参数。
但是还有this chapter,它指定在EE中,EJB会话bean所要求的规则集得到了扩展。
现在我们进入EJB规范,该规范要求在bean上使用no-arg构造函数。
这应该在Enterprise Bean Class
章中指出
该类必须定义一个不带参数的公共构造函数。
现在,最后继续讨论这是否应该起作用-例如使用CDI构造函数注入可以拥有EJB bean吗? 好吧,让我们看一下CDI TCK,这是所有实现和容器都必须通过的一组测试,以便能够声明它们实现了CDI。 在那里,我们可以看到this bean和this test using it-是的,这可以工作,但是您需要同时拥有两个构造函数。
答案 2 :(得分:2)
EJB被注册为CDI bean。但是首先,它们必须满足EJB规范的要求。
我想它只是通过提供no-args构造函数而起作用。