3

我试图通过使用 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<E> 注入。如果该方法只是创建并返回一个实现,它就可以正常工作。我只是不知道如何从 Instance<E> 中检查和选择候选人。查看“内容”的唯一方法似乎是 Iterator<E>。但是一旦我调用 next(),它就会尝试创建实现......不幸的是,为此调用了我的 @Produces 方法,从而创建了无限递归。我错过了什么?我如何检查候选人并选择一个?当然,我只想实例化其中一个...

提前感谢您的任何帮助和提示!

4

2 回答 2

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();

有关详细信息,请参阅通过编程查找文档获取上下文实例

于 2013-09-25T07:42:13.280 回答
1

芬奇,你这里的东西应该有用。它假设您有一个UEInterface已注释的实例@UESelect,例如

@UESelect("one")
public class UEOne implements UEInterface {
..
}

这是你期望它的工作方式吗?

于 2013-09-25T22:12:45.317 回答