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

时间:2017-06-20 09:10:19

标签: java generics java-ee cdi qualifiers

当使用限定符和泛型的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;

得到了相同的结果。

任何想法我如何使用注入限定符和泛型?

2 个答案:

答案 0 :(得分:2)

我重新创建了样本,它应该按预期工作。

限定符:

@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

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

答案 1 :(得分:1)

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

然而,第二种方法确实有效 - 我刚用Weld SE验证。 E.g:

@Inject
@SomeQualifier
SomeInterface<AnotherClass> instance;

我想您可能忘记重新编译代码或其他内容?仔细检查,因为我确定这是有效的。那,或者你在代码中还有其他一些问题。