CDI:基于对象类的注入

时间:2017-03-01 15:44:37

标签: java cdi

我有类层次结构,我想根据子类的类型使用CDI注入字段。 以下Java代码描述了这种情况:

@Stateless
public class A {
    @Inject
    @MyInjection
    D d;
    ...
    public void templateMethod(){...};
    protected void step1(){...};
    protected void step2(){...};
}

@Stateless
public class B extends A {
...
    protected void step1(){...};
    protected void step2(){...};
}

@Stateless
public class C extends A {
...
    protected void step1(){...};
    protected void step2(){...};
}

public class F {

    @Produces
    @MyInjection
    D myProducer(InjectionPoint ip){
        Class<?> clazz = ip.getMember().getDeclaringClass();

        //if clazz is B then inject one type

        //if clazz is C then inject other type

        //default inject default type
    }
}

这些bean作为EAR的一部分打包了适当的ejb.jar存档,并且在适当的位置有beans.xml文件。代码在使用Java EE 7的Wildfly 10服务器上执行。

使用这段代码我得到层次结构基类的类(在这个特定情况下是类A),这是我认为它是逻辑的,因为注入点 场确实在A级。 关键是我想基于子类进行区分,尽管我注入了超类。

我可以使用InjectionPoint类来实现吗?有没有办法实现这个目标?

更多关于我想用这段代码实现的目标。此层次结构实现模板方法设计模式,所有类都是具体的,您可以使用实现通用算法和特定步骤的类A,但您可以选择重新定义某些子类中的步骤。此外,还需要注入特定的类型D,根据子类可能会有所不同。

不幸的是,人们强烈希望不重新设计低音A类。所以我试图找到一种方法,使用CDI在基类中注入一些东西,而不是使用部署描述符。

2 个答案:

答案 0 :(得分:2)

根据您的问题,我了解您要确定将 bean 注入其中的内容。这可以通过以下方式实现:

@Produces
@MyInjection
D myProducer(InjectionPoint ip){
    // this will give you the class of the bean you injected into
    ip.getBean().getBeanClass();
}

为了完整性,您之前的解决方案使用了ip.getMember(),它返回Method个对象(或Field用于字段生成器)。因此,随后对getDeclaringClass()的调用将为您提供class A

答案 1 :(得分:0)

经过一些修修补补后,我找到了一种方法来实现我的问题所述的行为。这需要不同的CDI注入方法:而不是现场注入构造函数注入完成了这项工作。

public class A {
    D d;
    ...

    public A(){
        this.d = null;
    }

    @Inject
    public A(@MyInjection D d){
        this.d = d;
    }
    ...
    public void templateMethod(){...};
    protected void step1(){...};
    protected void step2(){...};
}

@Stateless
public class B extends A {
    ...
    public B(){
        super();
    }

    @Inject
    public B(@MyInjection D d){
        super(d);
    }
    ...
    protected void step1(){...};
    protected void step2(){...};
}

@Stateless
public class C extends A {
    ...
    public B(){
        super();
    }

    @Inject
    public B(@MyInjection D d){
        super(d);
    }
    ...
    protected void step1(){...};
    protected void step2(){...};
}

public class F {

    @Produces
    @MyInjection
    D myProducer(InjectionPoint ip){
        Class<?> clazz = ip.getMember().getDeclaringClass();

        //if clazz is B then inject one type

        //if clazz is C then inject other type

        //default inject default type
    }
}

以这种方式组织代码我能够基于叶类来区分注入,尽管可能无法实现不更改基类代码(API的一部分)的要求。