CDI Scope注解作用于Producer生产者方法的具体作用是什么
CDI生产者方法上Scope注解的作用说明
为什么会出现歧义依赖报错
CDI的依赖匹配规则是**仅根据Bean类型+限定符(Qualifier)**进行匹配,Scope(作用域)不属于限定符范畴,完全不参与依赖匹配过程。你提供的两个生产者方法都返回Thing类型,且都携带默认的@Default限定符,CDI无法区分两个实现,所以会抛出WELD-001409歧义依赖错误,这个是符合CDI规范的预期行为。
Scope注解在生产者方法上的核心作用
Scope的作用是控制生产者生成的Bean实例的生命周期和可见范围,和依赖区分无关,不同Scope的具体表现如下:
- 没有标注Scope的生产者方法,默认使用
@Dependent伪作用域:每次注入该类型Bean时,都会重新执行生产者方法生成全新实例,实例生命周期和注入它的宿主Bean完全绑定,宿主Bean销毁时该实例也会被销毁。
对应你的thingMaker方法,如果你在3个不同的Bean中注入该Thing,生产者方法会被调用3次,生成3个独立实例。 - 标注
@RequestScoped的生产者方法:生成的Thing实例生命周期绑定到当前HTTP请求,同一个请求内无论注入多少次,只会执行一次生产者方法生成共享实例,请求结束后实例自动销毁。 - 标注
@ApplicationScoped的生产者方法:生成的实例在整个应用生命周期内仅创建一次,全应用共享。 - 标注
@SessionScoped的生产者方法:生成的实例在同一个用户会话内共享,会话过期后销毁。
歧义问题的解决方案
如果确实需要同时存在多个返回同类型的生产者,需要自定义限定符(Qualifier)来区分,示例如下:
- 首先定义两个限定符注解:
import javax.inject.Qualifier; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Qualifier @Retention(RUNTIME) @Target({FIELD, PARAMETER, METHOD, TYPE}) public @interface DependentScopedThing {}
import javax.inject.Qualifier; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Qualifier @Retention(RUNTIME) @Target({FIELD, PARAMETER, METHOD, TYPE}) public @interface ReqScopedThing {}
- 给生产者方法加上对应限定符:
@Produces @DependentScopedThing public Thing thingMaker() { System.out.println("Making thingmaker"); return new ThingBean("thingMaker"); } @Produces @RequestScoped @ReqScopedThing public Thing thingMakerReq() { System.out.println("Making thingmakerReq"); return new ThingBean("thingMakerReq"); }
- 注入时通过限定符指定需要的实现:
// 注入Dependent作用域实例,每次注入生成新实例 @Inject @DependentScopedThing private Thing dependentThing; // 注入Request作用域实例,同请求内共享 @Inject @ReqScopedThing private Thing requestScopedThing;
内容的提问来源于stack exchange,提问作者Will Hartung
相关产品推荐
相关产品推荐

