You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),可以给工厂的生产者方法添加自定义限定符,注入时明确指定该限定符。

  1. 定义自定义限定符:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public @interface FactoryProvided {
}
  1. 修改工厂的生产者方法,添加自定义限定符:
@Produces
@RequestScoped
@FactoryProvided
public GService getGService() {
    final long currentTimeMillis = System.currentTimeMillis();
    return currentTimeMillis % 2 == 0 ? gServiceA : gServiceB;
}
  1. 在资源类中注入时指定该限定符:
@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:17:09