【发布时间】:2017-03-06 18:50:08
【问题描述】:
假设我有一个这样的界面:
public interface Converter<T> { /*...*/ }
假设在 CDI 环境中我已经成功地做到了这一点:
@Inject
@Any
private Instance<Converter<?>> converters;
(“成功”是指我可以执行以下操作并在输出中看到几个转换器,因此可以正确发现和提供 bean:
for (final Object o : converters) {
System.out.println("*** converter: " + o);
}
...所以 bean 发现不是问题。)
现在假设给定Integer.class,我想这样做:
final TypeLiteral<Converter<Integer>> typeLiteral = new TypeLiteral<Converter<Integer>>(){};
final Instance<Converter<Integer>> subInstance = converters.select(typeLiteral);
final Converter<Integer> converter = subInstance.get();
这很好用。
现在,在我的实际代码中,Integer.class 被传入,作为一个满足声明为Class<T> 的参数的值,所以我真正拥有的是:
final TypeLiteral<Converter<T>> typeLiteral = new TypeLiteral<Converter<T>>(){};
final Instance<Converter<T>> subInstance = converters.select(typeLiteral);
final Converter<T> converter = subInstance.get(); // this does not work
get() 调用失败,堆栈跟踪开始于如下所示:
org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type Converter<T> with qualifiers @Any
at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:105)
我必须怎么做才能使这个选择成功?
我注意到的一件事是堆栈报告找不到Converter<T>。这看起来很可疑:我原以为它会用Converter<Integer> 来代替,因为T“插槽”在运行时被Integer.class“填充”,但公平地说,我确实提供了一个new TypeLiteral<Converter<T>>(){},不是new TypeLiteral<Converter<Integer>>(){}。
无论如何,这一切都告诉我TypeLiteral<T> 使用T 作为要查找的类型,而不是“填充”T“槽”的实际值,实际上,没有声明为@ 的转换器987654340@,只有一个声明为implements Converter<Integer>的转换器,所以我担心我想在这里做的事情根本不可能。
【问题讨论】:
-
这可能是一个愚蠢的问题,但是您是否定义了一个 beans.xml,其中列出了(或未列出)您的可注入依赖项
-
是的;我应该提到我可以成功迭代
converters对象,并且可以看到找到了几个。 -
这可能与
new TypeLiteral<Converter<T>>(){}有关 -T在编译时未知,因此它将表示类型Converter<Object>,而不是Converter<T>。 -
@JosephEarl 我相信你是对的。看来我不能以这种方式做我想做的事。从这个角度来看,
Instance::select(TypeLiteral)仅适用于编译时可解析类型。能够在运行时进行选择也很好。那好吧。如果您写下您的评论作为答案,我会接受。 -
也许您可以让调用者将 TypeLiteral 传递给您的类/方法,以便在代码中创建 TypeLiteral 的位置已知类型,但您的类仍然可以是通用的并且不知道确切的类型.例如,这应该可以工作:
Converter<T> getConverter(TypeLiteral<Converter<T>> typeLiteral) { Instance<Converter<T>> subInstance = converters.select(typeLiteral); Converter<T> converter = subInstance.get(); return converter; },前提是调用者在编译时知道他们想要的转换器类型。