Java CDI:根据限定符动态选择实现?
我试图通过使用CDI使应用程序可扩展,但似乎我错过了一块拼图。
我想要的:拥有一个全局配置,定义要使用的接口的实现。 这些实现将具有@ImplDescriptor(type =“type1”)等注释。
我尝试了什么:
@Produces public UEInterface createUserExit(@Any Instance 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 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 注入。 如果方法只是创建并返回一个实现,它就可以正常工作。 我只是不知道如何检查并从Instance 中选择一个候选人。 查看“内容”的唯一方法似乎是迭代器。 但是一旦我调用next(),它就会尝试创建实现……不幸的是,为此调用我的@Produces方法,从而创建无限递归。 我错过了什么? 我如何检查候选人并选择一个? 当然我想只实例化其中一个……
在此先感谢任何帮助和提示!
我认为问题是你试图选择注释的类而不是使用注释作为选择器限定符。 使用该类直接搜索实现该类的实现。 您需要使用@ImplDescriptor类创建AnnotationLiteral,以使用它作为限定符来执行选择。 像这样创建一个扩展AnnotationLiteral的类。
public class ImplDescriptorLiteral extends AnnotationLiteral 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();
有关详细信息,请参阅通过编程查找文档获取上下文实例 。
芬奇,你在这里应该有所作为。 它假设你有一个UEInterface
的实例注释了@UESelect
,例如
@UESelect("one") public class UEOne implements UEInterface { .. }
这是你期望它如何工作?