CDI 4.0中@Specializes Bean未继承父类作用域?部署异常解析
问题背景
我们正将项目从JavaEE8升级至JakartaEE10(对应CDI 4.0),遇到以下部署异常问题:
- 最终war包包含一个无
beans.xml的隐式Bean归档JAR,其中定义了@Named("a")、@RequestScoped的类A - 主项目中通过
@Specializes注解定义了继承A的类B,同时有@Named("c")、@RequestScoped的类C注入了B - 代码未改动,但在Java17+JakartaEE10环境下运行时抛出异常:
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type B with qualifiers @Default - 给B添加作用域注解后恢复正常;排查发现CDI 3.0到4.0默认Bean发现模式从
ALL改为ANNOTATED,显式设置为ALL也可解决问题
核心疑问:@Specializes作为类级Bean注解,为何不属于Bean定义注解?
解答
首先明确CDI 4.0中ANNOTATED模式下的Bean定义注解范围:
CDI规范明确规定,只有能直接将一个类标记为CDI Bean的注解才属于Bean定义注解,具体包含:
- 所有作用域注解(如
@RequestScoped、@Singleton等) @Named@Alternative@Interceptor@Decorator
而@Specializes的定位是Bean修饰注解,它的作用是告知CDI:当存在继承关系时,用被@Specializes标记的子类Bean替代父类Bean的行为,但它本身不能单独将一个类定义为CDI Bean——也就是说,@Specializes必须依附于一个已经被Bean定义注解标记的类才能生效。
回到你的场景:
类A本身带有@Named和@RequestScoped(均为Bean定义注解),所以在任何发现模式下都会被识别为Bean;但类B只有@Specializes,没有任何Bean定义注解,在ANNOTATED模式下,CDI不会将B识别为合法Bean,因此注入B时会出现依赖找不到的异常。
两种可行的解决方式:
- 给类B添加一个Bean定义注解(比如你已经试过的作用域注解),让CDI在ANNOTATED模式下能识别它
- 将Bean发现模式改回
ALL,让CDI扫描所有类并识别为Bean(与JavaEE8/CDI3.0的行为一致)
内容的提问来源于stack exchange,提问作者Steven De Groote
相关产品推荐
相关产品推荐

