如何注入实现同一接口的两个不同类的两个实例? [英] How to inject two instances of two different classes which implement the same interface?

查看:75
本文介绍了如何注入实现同一接口的两个不同类的两个实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在用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 ...
}

这篇关于如何注入实现同一接口的两个不同类的两个实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆