为何无法在Weld/CDI中将Singleton Bean注入ApplicationScoped Bean?
Weld/CDI中Singleton Bean注入ApplicationScoped Bean失败的原因及解决办法
出现WELD-001408: Unsatisfied dependencies for type SomeSingletonBean with qualifiers @Default异常,通常是以下几个原因导致的:
Singleton Bean未被CDI正确识别
注意区分Java EE的EJB@Singleton和CDI的Bean规则:- 若使用EJB的
@javax.ejb.Singleton,需确保项目的EJB模块已正确激活,否则CDI无法扫描到该Bean; - 若想让类成为CDI管理的单例,更推荐使用CDI的
@javax.enterprise.context.ApplicationScoped(CDI中该注解的Bean生命周期就是全局单例,与Singleton语义一致); - 自定义的
@Singleton注解无法被CDI识别,需配合@Named或确保类在Bean存档范围内。
- 若使用EJB的
Bean类的访问权限不符合要求
SomeSingletonBean必须是public类,且拥有public的无参构造函数(默认构造函数即可,无需手动编写,但不能是私有)。CDI无法注入非public类或无合法构造函数的Bean。未配置Bean存档(Bean Archive)
CDI默认只会扫描包含beans.xml文件的模块作为Bean存档。如果SomeSingletonBean所在的模块没有beans.xml(哪怕是空文件),CDI不会将该类视为可注入的Bean。Java EE 7+可通过@ManagedBean或调整bean发现模式,但最稳妥的方式是在模块中添加beans.xml。限定符不匹配
异常中明确提到限定符为@Default,需检查:SomeSingletonBean是否被标注了自定义限定符(如@MyCustomQualifier),但注入点未添加对应限定符;- 反之,注入点是否使用了自定义限定符,但Bean上未标注。
模块依赖或类路径问题
若SomeSingletonBean在独立模块中,需确保该模块被当前应用正确依赖(如Maven依赖的scope为compile/provided),且CDI能跨模块扫描到该Bean。
正确示例
CDI单例Bean写法
import javax.enterprise.context.ApplicationScoped; @ApplicationScoped public class SomeSingletonBean { public void doBusiness() { // 业务逻辑 } }
注入到ApplicationScoped Bean
import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @ApplicationScoped public class AppScopedBean { @Inject private SomeSingletonBean singletonBean; // 使用singletonBean处理业务 }
EJB Singleton写法(需项目支持EJB)
import javax.ejb.Singleton; @Singleton public class SomeSingletonBean { // 业务方法 }
内容的提问来源于stack exchange,提问作者Benjamin
相关产品推荐
相关产品推荐

