【问题标题】:How to use dependency injection in JAXB unmarshalled objects?如何在 JAXB 解组对象中使用依赖注入?
【发布时间】:2013-07-03 16:58:17
【问题描述】:

我有一个工厂类

@ApplicationScoped /* 'ApplicationScoped' is not a must */
class MyFactory {

   @Inject
   private IService aService;

   ...
}

还有一个 JAXB 注释类

@XmlRootElement(name = "item")
class AnItem {

  @Inject
  MyFactory myFactory;

  ...
}

AnItem 由 JAXB 从 XML 文件实例化。 问题是myFactorynull。如果我将其替换为

...
MyFactory myFactory = new MyFactory();
...

那么myFactory.aService 为空。

如何在 JAXB 创建的类中使用依赖注入?

【问题讨论】:

  • 你用的是spring吗?如果您是,您可以使用 aspectj 进行基于构造函数的接线。
  • 很遗憾没有。我必须使用 Glassfish...

标签: java dependency-injection jaxb cdi


【解决方案1】:

以下解决方案的灵感来自Block of Adam Warski,另请参阅BeanManager Javadoc

首先我需要两个实用方法:

import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Utils {
  public static BeanManager getBeanManager() {
    try {
        InitialContext initialContext = new InitialContext();
        return (BeanManager) initialContext.lookup("java:comp/BeanManager");
    } catch (NamingException e) {
        throw new RuntimeException("Failed to retrieve BeanManager!", e);
    }
  }

  public static <T> T getBean(Class<T> c) {
    T result = null;
    BeanManager bm = getBeanManager();
    Set<Bean<?>> beans = bm.getBeans(c);
    if (! beans.isEmpty()) {
        Bean<?> bean = beans.iterator().next();
        result = c.cast(bm.getReference(bean, c, bm.createCreationalContext(bean)));
    }
    return result;
  }
}

AnItem 类必须像这样更改:

@XmlRootElement(name = "item")
class AnItem {

  MyFactory myFactory = Utils.getBean(MyFactory.class);

  ...
}

【讨论】:

  • 这当然是一种方法。看看 DeltaSpike,我们已经在 BeanProvider 类中处理了这一切。
  • DeltaSpike?从来没有听说过。有链接吗?
【解决方案2】:

我认为您在错误的类中有一些代码,这导致依赖关系以错误的方式出现,从而使对象难以正确构造。

Item 看起来像一个 newable 类(有时称为实体)。 Newable 类不是由您的容器创建的,而是由 service 类创建的。 Jaxb 是服务的一个示例。服务类由您的 DI 容器创建。

我会重新评估您是否需要让Item 持有对myFactory 的引用。您没有在问题中显示这一点,但Item 中必须有一个方法可以调用myFactory 中的某些内容。

此代码应从Item 移出到接受item 作为参数的不同类(可能是新服务)中。

【讨论】:

  • 我可以发布整个项目,但这不是重点。这只是一个(也许是愚蠢的)例子。但我的问题很明确:JAXB 实例化的类如何享受 CDI 的好处?但我没有问“我怎样才能重构我的项目?”
  • 我承认我并没有真正按要求提出问题,也没有足够的信息来判断我是否正确,但我认为这可能会有所帮助。
【解决方案3】:

CDI bean 应该是容器管理的,这意味着如果您使用new 创建它们,您将不会获得任何容器服务(注入、拦截、装饰器等)。您需要 @Inject 您的工厂类才能使注入正常工作。

【讨论】:

  • 请仔细阅读我的问题。实际上这是JAXB创建的类默认不管理的问题。我希望有一种方法可以让 JAXB 与 CDI 一起工作,因为两者都是 javee 的一部分。
  • 这需要更新 JAXB 规范。我强烈建议您找到并联系 JAXB 的规范负责人/维护负责人并提出要求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
相关资源
最近更新 更多