不能将限定符与包含泛型的接口一起使用



遇到带有限定符和泛型的 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 {}

因此,当我将其注入某个豆子(我的项目中的单例(时:

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

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

Unsatisfied dependencies for type SomeInterface with qualifiers @SomeQualifier

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

尝试像这样注射:

@Inject
@SomeQualifier
SomeInterface<AnotherClass> instance;

得到相同的结果。

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

您的第一种方法不起作用的原因是您违反了 CDI 规范可分配性规则(第一行(。简而言之 - 注入原始类型仅适用于未绑定/Object类型。

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

@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);
    }
}

还有一个测试类:

@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));
    }
}

您可以复制此类并按以下方式运行它:

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

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

最新更新