Quarkus中@Produces生产多实现接口引发依赖歧义错误
解决CDI依赖歧义问题
你遇到的AmbiguousResolutionException是因为CDI容器找到了3个能提供GService类型的bean:GServiceAImpl、GServiceBImpl以及MyServiceFactory中的生产者方法,且三者都带有默认的@Default限定符,导致注入时无法确定选择哪一个。以下是两种直接有效的解决方式:
方式一:禁用实现类的CDI bean暴露(推荐)
既然你的核心需求是通过工厂动态选择GServiceAImpl或GServiceBImpl,可以让CDI容器不再将这两个实现类当作GService类型的候选bean,只保留工厂的生产者方法作为唯一来源。
给两个实现类添加@Vetoed注解,告诉CDI忽略它们的bean注册:
@ApplicationScoped @Vetoed public class GServiceBImpl implements GService { @Override public String doIt() { return "B"; } } @ApplicationScoped @Vetoed public class GServiceAImpl implements GService { @Override public String doIt() { return "A"; } }
这样容器中只有工厂的生产者方法能提供GService,注入时就不会有歧义了。
方式二:使用自定义限定符区分bean
如果需要保留实现类的CDI bean身份(比如其他地方要直接注入GServiceAImpl或GServiceBImpl),可以给工厂的生产者方法添加自定义限定符,注入时明确指定该限定符。
- 定义自定义限定符:
@Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) public @interface FactoryProvided { }
- 修改工厂的生产者方法,添加自定义限定符:
@Produces @RequestScoped @FactoryProvided public GService getGService() { final long currentTimeMillis = System.currentTimeMillis(); return currentTimeMillis % 2 == 0 ? gServiceA : gServiceB; }
- 在资源类中注入时指定该限定符:
@Path("/doit") public class GResource { @Inject @FactoryProvided GService gService; @GET @Produces(MediaType.TEXT_PLAIN) public String doIt() { return gService.doIt(); } }
这种方式明确告诉容器要选择工厂提供的GService实例,避免和两个实现类的bean冲突。
内容的提问来源于stack exchange,提问作者Fabrizio Stellato
相关产品推荐
相关产品推荐

