我正在尝试通过使用CDI使应用程序可扩展,但似乎我错过了一个难题。
我想要的: 具有全局配置,该配置将定义要使用的接口的实现。这些实现会有@ImplDescriptor(type =“type1”)等注释。
我尝试了什么:
@Produces
public UEInterface createUserExit(@Any Instance<UEInterface> instance, InjectionPoint ip) {
Annotated annotated = ip.getAnnotated();
UESelect ueSelect = annotated.getAnnotation(UESelect.class);
if (ueSelect != null) {
System.out.println("type = " + ueSelect.type());
}
System.out.println("Inject is ambiguous? " + instance.isAmbiguous());
if (instance.isUnsatisfied()) {
System.out.println("Inject is unsatified!");
return null;
}
// this would be ok, but causes an exception
return instance.select(ueSelect).get();
// or rather this:
for (Iterator<UEInterface> it = instance.iterator(); it.hasNext();) {
// problem: calling next() will trigger instantiation which will call this method again :(
UEInterface candidate = it.next();
System.out.println(candidate.getClass().getName());
}
}
这段代码接近我见过的一个例子:@Produces方法将用于选择和创建实例,候选列表将作为Instance&lt; E&gt;注入。如果方法只是创建并返回一个实现,它就可以正常工作。我只是不知道如何检查并从实例&lt; E&gt;中选择候选人。查看“内容”的唯一方法似乎是迭代器&lt; E&gt;。但是一旦我调用next(),它就会尝试创建实现......不幸的是,为此调用我的@Produces方法,从而创建无限递归。我错过了什么?我如何检查候选人并选择一个?当然我想只实例化其中一个...
提前感谢任何帮助和提示!
答案 0 :(得分:3)
我认为问题是你试图选择注释的类而不是使用注释作为选择器限定符。使用该类直接搜索实现该类的实现。您需要使用@ImplDescriptor类创建AnnotationLiteral,以使用它作为限定符来执行选择。像这样创建一个扩展AnnotationLiteral的类。
public class ImplDescriptorLiteral extends AnnotationLiteral<ImplDescriptor> implements ImplDescriptor {
private String type;
public ImplDescriptorLiteral(String type) {
this.type = type;
}
@Override
public String type() {
return type;
}
}
然后你可以使用你想要的类型将这个类的实例传递给select方法。
instance.select(new ImplDescriptorLiteral("type1")).get();
有关详细信息,请参阅Obtaining a contextual instance by programmatic lookup documentation。
答案 1 :(得分:1)
芬奇,你在这里应该有所作为。它假设您有一个注释UEInterface
的{{1}}实例,例如
@UESelect
这是你期望它的工作方式吗?