不能对包含泛型的接口使用限定符

Can't use qualifiers with interface that consist generics

遇到带有限定符和泛型的 cdi 不起作用的情况。

例如,我有这样的界面:

public interface SomeInterface<T> {
   T someMethod(Set<T> set);
}

它的实现(以及其他几个带有其他限定符的实现):

@SomeQualifier
public class SomeClass implements SomeInterface<AnotherClass> {
    AnotherClass someMethod(Set<AnotherClass> set) {...some logic...}
}

还有一些这样的限定词:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
public @interface SomeQualifier {}

所以,当我将其注入某个 bean(我项目中的单例)时:

@Singleton
@Startup
public class SomeSingleton {
  @Inject
  @SomeQualifier
  SomeInterface instance;

  ..usage...
}

我在部署过程中遇到异常,例如

Unsatisfied dependencies for type SomeInterface with qualifiers @SomeQualifier

但是当我在不使用泛型的情况下使用所有这些时 - 一切正常!

试过这样注射:

@Inject
@SomeQualifier
SomeInterface<AnotherClass> instance;

得到相同的结果。

知道如何将注入与限定符和泛型一起使用吗?

我已经重新创建了样本,它应该可以正常工作。

预选赛:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER})
public @interface BasicSample {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER})
public @interface IntegerSample {
}

实现:

public interface SampleGenericInterface<T> {

    T process(Set<T> values);

}

还有两个实现:

@BasicSample
@ApplicationScoped
public class BasicSampleGenericInterface implements SampleGenericInterface<BigDecimal> {

    @Override
    public BigDecimal process(Set<BigDecimal> values) {
        return values.stream().max(BigDecimal::compareTo).orElse(null);
    }

}


@IntegerSample
@ApplicationScoped
public class IntegerSampleGenericInterface implements SampleGenericInterface<Integer> {

    @Override
    public Integer process(Set<Integer> values) {
        return values.stream().min(Integer::compareTo).orElse(null);
    }

}

还有一个测试class:

@ApplicationScoped
public class CdiTest {

    private static final Logger LOG = Logger.getLogger(CdiTest.class.getName());

    @Inject
    @BasicSample
    private SampleGenericInterface<BigDecimal> bigDecimalSampleGenericInterface;

    @Inject
    @IntegerSample
    private SampleGenericInterface<Integer> integerSampleGenericInterface;

    void start(@Observes ContainerInitialized containerInitialized) {
        Set<BigDecimal> bigDecimals = new HashSet<>();
        bigDecimals.add(BigDecimal.valueOf(837373));
        bigDecimals.add(BigDecimal.valueOf(8299));
        bigDecimals.add(BigDecimal.valueOf(4545454));
        LOG.log(Level.INFO, "Big Decimal: {0}", bigDecimalSampleGenericInterface.process(bigDecimals));
        Set<Integer> integers = new HashSet<>();
        integers.add(72);
        integers.add(3452);
        integers.add(458923);
        LOG.log(Level.INFO, "Integers: {0}", integerSampleGenericInterface.process(integers));
    }
}

您可以将此 class 和 运行 复制为:

java org.jboss.weld.environment.se.StartMain

在解析过程中,将考虑通用参数和限定符注释。

您的第一种方法不起作用的原因是因为您违反了 CDI spec assignability rules(第一行)。简而言之 - 注入原始类型仅适用于未绑定/Object 类型。

但是,第二种方法确实有效——我刚刚使用 Weld SE 进行了验证。例如:

@Inject
@SomeQualifier
SomeInterface<AnotherClass> instance;

我想你可能忘了重新编译你的代码什么的?仔细检查,因为我确定这有效。那,或者你的代码有其他问题。