【问题标题】:CDI Injection into existing object instance - worked with CDI 1.0 but not with CDI 1.1CDI 注入现有对象实例 - 使用 CDI 1.0 但不适用于 CDI 1.1
【发布时间】:2016-06-19 09:49:35
【问题描述】:

由于我必须使用的框架的限制,我需要注入现有的对象实例(不能像往常一样通过 CDI 本身创建它们)。我的注入点标有@EJB 或@Inject。

使用 JBoss EAP 6.4、Java EE 6 和 CDI 1.0,使用以下代码可以完美运行:

public class DispatcherUtils {

    public static <T> void inject(T anObject) {
        BeanManager beanManager = getBeanManager();
        Class<T> objClass = (Class<T>) anObject.getClass();
        AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(objClass);
        InjectionTarget<T> injectionTarget = beanManager.createInjectionTarget(annotatedType);
        CreationalContext<T> context = new IgnorantCreationalContext<>();
        injectionTarget.inject(anObject, context);
        injectionTarget.postConstruct(anObject);
    }

    private static BeanManager getBeanManager() {
        try {
            return (BeanManager) InitialContext.doLookup("java:comp/BeanManager");
        } catch (final NamingException e) {
            e.printStackTrace();
        }
        return null;
    }

}

如果我尝试在 JBoss EAP 7.0、Java EE 7 和 CDI 1.1 中做同样的事情,只有标有 @Inject 的注入点会被注入到目标对象中,标有 @EJB 的注入点不会被注入(它们的值仍然为空)。

我不明白为什么会这样。

有什么方法可以使用 JBoss EAP 7.0、Java EE 7 和 CDI 1.1 注入现有对象并同时填充 @EJB 注入点?


更新,2016-06-19,20:11

我刚刚发现只要我要注入的对象具有无参数构造函数,上述模式就可以工作。

示例 - 这有效:

public class ExampleBean {

    private Dispatcher dispatcher;

    @Inject
    private SomeCdiBean someCdiBean;

    @EJB
    private SomeEjbService someEjbService;

    public ExampleBean() {
    }

    public ExampleBean(Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

}

虽然这不起作用:

public class ExampleBean {

    private Dispatcher dispatcher;

    @Inject
    private SomeCdiBean someCdiBean;

    @EJB
    private SomeEjbService someEjbService;

    public ExampleBean(Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

}

在这种情况下,为什么 CDI 会检查默认构造函数的存在? (注意:bean 不是由 CDI 创建的,所以构造函数应该没有任何区别)

【问题讨论】:

  • 您的IgnorantCreationalContext 是什么样的? DeltaSpike 具有相同的功能,并且在 Wildfly 10 上运行良好:github.com/apache/deltaspike/blob/master/deltaspike/core/api/… 也许您会考虑切换到该功能?
  • 那是我的 IgnorantCreationalContext gist.github.com/t3chris/36d627528b5d059a272afd4ed8ccd148 我也尝试过使用 Deltaspike,但看到相同的结果 @Inject 有效,但 @EJB 仍为空值。
  • @JohnAment:我已经更新了我原来的问题。你有什么方法可以让 CDI 忽略默认构造函数的缺失吗?
  • 我相当有信心您的问题是您的创作背景。这会给你带来不同的结果吗? CreationalContext&lt;T&gt; creationalContext = beanManager.createCreationalContext(null); 而不是实例化你的上下文。
  • 很遗憾,您的建议没有任何作用...您知道我还能做些什么来解决这个问题吗?

标签: jakarta-ee jboss cdi


【解决方案1】:

可能的问题是您的ExampleBean 没有 no-args 构造函数不被视为managed bean。而集成商(Wildfly、EAP、glassfish...)只能将 EE 资源注入(@EJB 是 EE 资源注入)提供给 managed beans。

引用Weld doc:

集成商可能希望使用 InjectionServices 来提供 Weld 提供的额外字段或方法注入。与 Java EE 环境的集成可以使用 InjectionServices 为托管 bean 提供 EE 资源注入。

要使ExampleBean 成为managed bean 并且不使用无参数构造函数,您需要声明一个带有@Inject 注释的构造函数。

虽然我只是在这里胡乱猜测,并不能确定你为什么说它适用于 EAP 6 和 CDI 1.0。

另外还有一个注意事项——据我所知,EAP 7 包含 CDI 1.2(而不是 1.1)。

【讨论】:

  • 你所说的关于 ExampleBean,它不是托管 bean,我完全同意。然而,到目前为止,我们过去只是简单地走这条路,因为它工作得很好。我现在将寻求一种解决方案,它允许我们告诉 CDI 引擎可以注入一个看起来不像托管 bean 的实例(就像它在 EAP 6.x 中所做的那样)。应该没有任何问题,因为我们事先已经正确地创建了该 bean。关于 CDI 1.2,你当然是对的,我的错。
猜你喜欢
  • 1970-01-01
  • 2016-07-25
  • 2023-03-10
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 2017-06-03
  • 2016-08-27
相关资源
最近更新 更多