【问题标题】:CDI Injection in created objects创建对象中的 CDI 注入
【发布时间】:2016-02-06 19:18:24
【问题描述】:

我们有一个使用 JPA 但不使用 CDI 或 EJB 的大型 pre-JEE5 应用程序,因此 EntityManager 不会被注入 DAO,而是使用

Persistence.createEntityManagerFactory(...).createEntityManager()

,然后存储在ThreadLocal变量中。这个获取实体管理器的脏活被封装在DAO使用的实用程序类EntityManagerUtil中,因此业务逻辑不处理低级实体管理器的东西;另外,这个应用程序使用aspectj和annotations来创建事务边界,事务方面使用与DAO相同的EntityManagerUtil类来获取实体管理器来创建事务。

我们现在需要将此应用程序迁移到 Wildfly 9。它不能开箱即用,因为 aspectj 不能在 wildfly 中部署,所以我们创建和提交事务的方面不适用,并且没有任何效果。为了让它工作,我们需要将EntityManager注入DAO并使用EJB或CDI事务机制,但这似乎也意味着我们需要将DAO注入到任何使用它们的类中,然后将这些类注入到更高的类中在调用层次结构上,依此类推(好像该类是使用“new”创建的,它不受容器管理,并且没有任何东西注入其中)。由于应用程序很大,而且我们到处都有对象实例化,这似乎是不可能完成的任务。

所以我想知道是否可以在 DAO 和更低级别隔离注入使用,因此使用 DAO 的调用者代码不会改变,并且仍会使用“new”创建 DAO,但 DAO 将使用注入的实体管理器和CDI 还是 EJB 事务?

欢迎提出建议,谢谢!

【问题讨论】:

  • 在更高层次上,注入manger的时候,能不能保存在一个线程本地?稍后,新的 DAO 可以从本地线程中查找。
  • 您能否详细说明您的EntityManagerUtil 是如何使用的?您很可能必须(由服务器)完全管理,或者您必须将容器排除在外。

标签: jakarta-ee dependency-injection transactions cdi wildfly


【解决方案1】:

我会投票支持像 SpringCDI 这样的 IoC 容器,因为 EJB 不会为您提供自定义依赖注入 - 只能注入其他 EJB 和预定义的服务器资源(编辑:当然如果应用程序使用 CDI 和 EJB,那么 cdi bean 也可以被注入)。

我会尝试将BeanManager(或ApplicationContext,如果使用Spring)包装在某种可从任何地方访问的静态实用程序类中 - 特别是在业务逻辑中(static 将是一种临时方法,替代方法是使用 WildFly 服务器及其 JNDI 功能)。

但是,如果应用程序使用 EAR 存档和多个类加载器,这可能会很棘手(但我猜,如果应用程序现在使用 ThreadLocal 模式,那么它已经可以很好地处理多个“单例”了)。

事务边界可以通过使用@javax.transaction.Transactional 注释所有DAO 来实现。后来BeanManager/ApplicationContext本身可以用于在业务类中创建这样的DAO。


顺便说一句:当迁移到 WildFly 9 这样的 pre-JEE5 应用程序时,也许这些事务问题将是最小的问题之一。您还必须处理服务器提供的大量新库(可能与已使用的库不兼容)、类加载器问题等等......

【讨论】:

  • 您绝对可以将@Inject CDI 托管资源转换成EJB 的。在大多数情况下,您甚至可以@Inject EJB 本身。
  • @JamesR.Perkins 似乎是一个毫无意义的评论。 EJB 仍然没有为您提供 IoC 功能。我们都知道将 EJB 和 CDI 结合起来是可能的——但是为什么作者会想在 EJB 方面遇到更大的问题呢?
  • 我想我误解了你的“只能注入其他 EJB 和预定义的服务器资源”的说法。我很抱歉。
  • @JamesR.Perkins 不,确实你是对的。我澄清了这个误导性的句子。谢谢。
【解决方案2】:

你当然可以做你所说的那种本地化注入,但是如果没有像 Apache DeltaSpike 这样的 cdi 扩展框架,它会有点冗长。

使用 DeltaSpike,您可以简单地说 BeanProvider.getContextualInstance(MyInterface.class); 将内容“注入”到您自己构建的对象中。

如果没有 DeltaSpike 或等效项,您仍然可以使用 jndi 查找来访问 BeanManager 以“注入”您的 bean,但 api 不是那么好。

关于 jndi,您还可以使用 EJB 实现数据访问,并通过 jndi 查找将对它们的访问封装在您旧的自行创建的 DAO 中。不太好,但至少可以让您访问容器管理的事务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-04
    • 2014-01-27
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多