在用Java处理CDI时,我想注入两个不同类的两个实例,实现相同的接口.
When dealing with CDI in java, I want to inject two instances of two different classes, implementing the same interface.
据我了解,我可以注入未实现接口的类的实例,例如:
As I understand, I can inject an instance of a class which does not implement an interface, e.g.:
class MyClass { // ... } class XY { @Inject MyClass myClass; }当我的类实现接口时,我必须通过接口名称声明成员(并指定具体实现):
When my class implements an interface I have to declare the member by the interface name (and specify the concrete implementation):
class MyClass implements MyInterface { // ... } class XY { @Inject MyInterface myClass; }但是,一旦我想注入不同的实现,就会得到找不到带有限定词的Api类型[...]"
But as soon as I want to inject different implementations, I get the "Api type [...] is not found with the qualifiers" exception:
class MyClassOne implements MyInterface { // ... } class MyClassTwo implements MyInterface { // ... } class XY { @Inject MyClassOne myClassOne; @Inject MyClassTwo myClassTwo; }对于任何尝试尝试或在哪里继续阅读的想法,我都表示感谢(搜索此主题的明显关键字会给出非常不确定的结果).预先感谢!
I appreciate any ideas what to try or where to continue reading (the obvious keywords for a search on this topic give very unspecific results). Thanks in advance!
推荐答案为了注入不同的实例,有不同的方法来构造和注入bean.
In order to inject different instances, there are different ways to construct and inject beans.
方法1 :
@Qualifier @Retention(RUNTIME) @Target({FIELD, TYPE, METHOD}) public @interface ClassifierOne { } @Qualifier @Retention(RUNTIME) @Target({FIELD, TYPE, METHOD}) public @interface ClassifierTwo { }这些限定符可用于您的施工参数注入或setter注入级别的班级部分.
These qualifiers can be used in your class part of construction parameter injection or setter injection level.
@ClassifierOne public class MyClassOne implements MyInterface { // ... } @ClassifierTwo public class MyClassTwo implements MyInterface { // ... } public class XY { private final MyInterface myClassOne; private final MyInterface myClassTwo; @Inject public XY ( @ClassifierOne MyInterface myClassOne, @ClassifierTwo MyInterface myClassTwo ) { this.myClassOne = myClassOne; this.myClassTwo = myClassTwo; } }方法2 :使用@Produces
Approach 2: Use of @Produces
@Qualifier @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) public @interface MyClassType { ClassImplName value(); } public enum ClassImplName { CLASS_ONE(MyClassOne.class), CLASS_TWO(MyClassTwo.class); private Class<? extends MyInterface> classType; private ClassImplName(Class<? extends MyInterface> clazz) { this.classType = clazz; } public Class<? extends MyInterface> getClassType(){ return classType; } } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) public @interface ClassType { ClassImplName value(); }以上自定义限定符将允许您通过删除生产者方法中的abibuaty来选择实现类型.并且,您可以使用下面提到的MyClassFactory来生成接口.这种机制会很有效,因为它在注入bean的地方使用了InjectionPoint.
Above custom qualifiers will allow you to chose type of implementation by removing abibuaty in producer method. And, you can use below mentioned MyClassFactory to produce interfaces. This mechanism would be efficient as it uses InjectionPoint where the bean is injected.
public class MyInterfaceFactory { @Produces @MyClassType public MyInterface createMyClasses(@Any Instance<MyInterface> instance, InjectionPoint injectionPoint) { Annotated annotated = injectionPoint.getAnnotated(); ClassType classTypeAnnotation = annotated.getAnnotation(ClassType.class); Class<? extends MyInterface> classType = classTypeAnnotation.value().getClassType(); return instance.select(classType).get(); } }最后,您可以在类中使用这些生成的实例.
Finally, you can use these generated instances in your class.
public class XY { @Inject @ClassType(ClassImplName.CLASS_ONE) @MyClassType private MyInterface myClassOne; @Inject @ClassType(ClassImplName.CLASS_TWO) @MyClassType private MyInterface myClassTwo; // Other methods using injected beans ... }更多推荐
如何注入实现同一接口的两个不同类的两个实例?
发布评论