简体   繁体   English

CDI:基于对象类的注入

[英]CDI: Injection based on object class

I have class hierarchy where I would like to inject field using CDI based on type of subclass. 我有一个类层次结构,我想根据子类的类型使用CDI注入字段。 This situation is described in following Java code: 以下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
    }
}

These beans are packaged appropriate ejb.jar archive as part of EAR and there is beans.xml file in proper place. 这些Bean作为EAR的一部分打包为适当的ejb.jar归档文件,并且在适当位置有beans.xml文件。 The code is executing on Wildfly 10 server using Java EE 7. 该代码正在使用Java EE 7在Wildfly 10服务器上执行。

Using this code I get class of hierarchy base class (in this specific case class A), which is when I think about it logical, beacause InjectionPoint field is indeed in class A. The point is that I would like to make distinction based on subclasses although I do inject in superclass. 使用此代码,我得到了层次结构基类的类(在这种情况下为A类),这是我认为合乎逻辑的原因,因为InjectionPoint字段确实在A类中。关键是我想根据子类进行区分尽管我确实注入了超类。

Could I achieve this using InjectionPoint class? 我可以使用InjectionPoint类实现此目的吗? Is there any possible way to achieve this? 有什么可能的方法来实现这一目标?

More on that what I would like to achieve with this piece of code. 这是我想通过这段代码实现的更多信息。 This hierarchy implements template method Design Pattern and all classes are concrete, you can use class A which implements general algorithm and specific steps, but you can opt out to redefine steps in some subclass. 该层次结构实现了模板方法“设计模式”,并且所有类都是具体的,您可以使用实现通用算法和特定步骤的类A,但是可以选择退出以重新定义某些子类中的步骤。 Also there is need to inject specific type D, which might be different based on sublclass. 另外,还需要注入特定的类型D,该类型根据子类可能有所不同。

Unfortunately there is strong desire not to redesign bass class A. So I am trying to find I way to inject something in base class using CDI and not using deployment descriptor. 不幸的是,强烈希望不要重新设计低音类A。因此,我试图找到一种方法,使用CDI而不是使用部署描述符在基类中注入某些东西。

From your question I understood that you want to determine what bean are you injecting it into. 根据您的问题,我了解到您想确定要将其注入到哪种bean中。 This can be achieved in the following way: 这可以通过以下方式实现:

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

For completeness, your previous solution used ip.getMember() which returns a Method objects (or Field for field producers). 为了完整ip.getMember() ,您先前的解决方案使用了ip.getMember() ,该ip.getMember()返回一个Method对象(或字段生产者的Field )。 Therefore, subsequent call to getDeclaringClass() will give you class A . 因此,随后对getDeclaringClass()调用将为您提供class A

After a bit of tinkering I found a way to achieve behaviour stated in my question. 经过一番修补后,我找到了一种解决问题的方法。 This required different approach to CDI injection: instead of field injection constructor injection did the job. 这要求采用不同的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
    }
}

Organizing code this way I am able to discriminate injection based on leaf classes, although the requirement of not changing code of the base class (part of an API) might not be possible to achieve. 尽管不更改基类(API的一部分)的代码的要求可能无法实现,但通过这种方式组织代码,我可以根据叶类区分注入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM