如何注入实现相同接口的两个不同 类 的两个实例?
How to inject two instances of two different classes which implement the same interface?
在 java 中处理 CDI 时,我想注入两个不同 classes 的两个实例,实现相同的接口。
据我所知,我可以注入一个 class 的实例,它没有实现接口,例如:
class MyClass {
// ...
}
class XY {
@Inject MyClass myClass;
}
当我的class实现一个接口时,我必须通过接口名称声明成员(并指定具体实现):
class MyClass implements MyInterface {
// ...
}
class XY {
@Inject MyInterface myClass;
}
但是一旦我想注入不同的实现,我就会得到 "Api type [...] is not found with the qualifiers" 异常:
class MyClassOne implements MyInterface {
// ...
}
class MyClassTwo implements MyInterface {
// ...
}
class XY {
@Inject MyClassOne myClassOne;
@Inject MyClassTwo myClassTwo;
}
我很欣赏尝试什么或在哪里继续阅读的任何想法(搜索此主题的明显关键字会给出非常不明确的结果)。
提前致谢!
为了注入不同的实例,有不同的方法来构造和注入bean。
方法 1:
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface ClassifierOne {
}
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface ClassifierTwo {
}
这些限定符可用于您的 class 部分构造参数注入或 setter 注入级别。
@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
@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。
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();
}
}
最后,您可以在 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 ...
}
在 java 中处理 CDI 时,我想注入两个不同 classes 的两个实例,实现相同的接口。
据我所知,我可以注入一个 class 的实例,它没有实现接口,例如:
class MyClass {
// ...
}
class XY {
@Inject MyClass myClass;
}
当我的class实现一个接口时,我必须通过接口名称声明成员(并指定具体实现):
class MyClass implements MyInterface {
// ...
}
class XY {
@Inject MyInterface myClass;
}
但是一旦我想注入不同的实现,我就会得到 "Api type [...] is not found with the qualifiers" 异常:
class MyClassOne implements MyInterface {
// ...
}
class MyClassTwo implements MyInterface {
// ...
}
class XY {
@Inject MyClassOne myClassOne;
@Inject MyClassTwo myClassTwo;
}
我很欣赏尝试什么或在哪里继续阅读的任何想法(搜索此主题的明显关键字会给出非常不明确的结果)。 提前致谢!
为了注入不同的实例,有不同的方法来构造和注入bean。
方法 1:
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface ClassifierOne {
}
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface ClassifierTwo {
}
这些限定符可用于您的 class 部分构造参数注入或 setter 注入级别。
@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
@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。
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();
}
}
最后,您可以在 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 ...
}