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

CDI中带不同限定符的生产者方法注入歧义问题及解决方案咨询

Why the AmbiguousResolutionException Happens

This is all down to CDI's qualifier matching rules: a producer method is considered a candidate if its set of qualifiers includes all the qualifiers specified at the injection point (extra qualifiers on the producer are allowed).

When you inject with just @Inject @Qualifier1 MyBean:

  • produce1 has exactly @Qualifier1—it's an exact match, so it's a valid candidate.
  • produce2 has both @Qualifier1 and @Qualifier2—since it includes all the qualifiers from the injection point (@Qualifier1), CDI also considers it a valid candidate.

CDI can't pick between them by default, hence the AmbiguousResolutionException.

Solution 1: Use @Priority (Simplest Fix)

Since you can't modify the third-party produce1, you can give your custom produce2 a lower priority. This tells CDI to prefer the third-party producer when both are candidates, but still use your producer when the injection point requires both qualifiers.

Update your producer like this:

@ApplicationScoped
public class MyProducer {
    // Third-party producer (unmodifiable)
    // @Produces
    // @Qualifier1
    // MyBean produce1(InjectionPoint injectionPoint) { ... }

    @Produces
    @Qualifier1
    @Qualifier2
    @Priority(-1) // Lower than the default priority of 0
    MyBean produce2(InjectionPoint injectionPoint) { ... }
}

How This Works:

  • When injecting with only @Qualifier1: Both producers are candidates, but produce1 has the default priority (0) which is higher than produce2's -1. CDI picks produce1 automatically, no ambiguity.
  • When injecting with both @Qualifier1 and @Qualifier2: Only produce2 matches (since produce1 doesn't have @Qualifier2), so it gets selected.
Solution 2: Custom Conditional Producer (CDI 2.0+)

If you're using CDI 2.0 or newer, you can create a custom condition that only activates produce2 when the injection point has both qualifiers. This eliminates ambiguity at the source.

First, create a condition class:

public class BothQualifiersPresentCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context) {
        InjectionPoint injectionPoint = context.get(InjectionPoint.class);
        if (injectionPoint == null) return false;

        boolean hasQualifier1 = injectionPoint.getQualifiers()
            .stream()
            .anyMatch(q -> q.annotationType().equals(Qualifier1.class));
        boolean hasQualifier2 = injectionPoint.getQualifiers()
            .stream()
            .anyMatch(q -> q.annotationType().equals(Qualifier2.class));

        return hasQualifier1 && hasQualifier2;
    }
}

Then apply the condition to your producer:

@ApplicationScoped
public class MyProducer {
    // Third-party producer (unmodifiable)
    // @Produces
    // @Qualifier1
    // MyBean produce1(InjectionPoint injectionPoint) { ... }

    @Produces
    @Qualifier1
    @Qualifier2
    @Conditional(BothQualifiersPresentCondition.class)
    MyBean produce2(InjectionPoint injectionPoint) { ... }
}

How This Works:

  • produce2 will only be considered a candidate if the injection point has both @Qualifier1 and @Qualifier2. When injecting with just @Qualifier1, only produce1 is a candidate, so no ambiguity.

内容的提问来源于stack exchange,提问作者Simon Wick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:57:27