簡體   English   中英

如何注入實現同一接口的兩個不同類的兩個實例?

[英]How to inject two instances of two different classes which implement the same interface?

在用Java處理CDI時,我想注入兩個不同類的兩個實例,實現相同的接口。

據我了解,我可以注入未實現接口的類的實例,例如:

class MyClass {
  // ...
}

class XY {
  @Inject MyClass myClass;
}

當我的類實現接口時,我必須通過接口名稱聲明成員(並指定具體實現):

class MyClass implements MyInterface {
  // ...
}

class XY {
  @Inject MyInterface myClass;
}

但是,一旦我想注入不同的實現,就會出現“找不到帶有限定詞的Api類型[...]”異常:

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 {
}

這些限定符可用於構造參數注入或設置器注入級別的班級部分。

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

上面的自定義限定符將允許您通過刪除生產者方法中的適當選項來選擇實現類型。 並且,您可以使用下面提到的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();
    }
}

最后,您可以在類中使用這些生成的實例。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM