【问题标题】:cdi injected dependency resolved to null in a bean created by a producer methodcdi 注入的依赖在生产者方法创建的 bean 中解析为 null
【发布时间】:2018-12-17 13:02:30
【问题描述】:

我正在尝试将依赖项注入到 bean (Some/OtherImpl) 中,并使用 @Named 进行注释,但是当新的该 bean 的实例是在控制器 (MyCtrl) 中使用其生产者方法创建的。

但是,如果我尝试将 ConfigurationService 直接注入控制器,则方法 Resources#getConfiguratioService 会执行并创建 ConfigurationService 的新实例,该实例将被注入控制器。

看起来是这样的

public class Resources() {
  @Produces
  public ConfigurationService getConfigurationService() {
      return new ConfigurationService(Constants.CONFIG);
  }
}

public abstract class MyAbstractClass {

  @Inject
  private transient ConfigurationService configurationService; // getter+setter

}

@Named
public class SomeImpl extends MyAbstractClass implements Serializable {
  // ...
}

@Named
public class OtherImpl extends MyAbstractClass implements Serializable {
  // ...
}

@Named
@ViewScoped
public class MyCtrl {

  @Inject
  private SomeImpl someImpl;

  @Produces
  public SomeImpl getSomeImpl() {
    return new SomeImpl(MyStringParam);
  }

}

你能告诉我我在这里做错了什么吗?有没有办法解决它?每一个提示将不胜感激。提前谢谢!

【问题讨论】:

  • 如果它是由new创建的,它不受CDI控制,不会发生依赖注入。

标签: jakarta-ee cdi


【解决方案1】:

这里的问题是您正在使用 new 关键字“手动”创建 SomeImpl 的实例。 在这种情况下,您创建/提供对象,不会发生注入,然后你把这个对象交给 CDI。从那里开始,任何SomeImpl 类型和带有默认限定符的注入点都将使用您的生产者来创建bean。生产者通常是一种将非 CDI 对象转换为 CDI bean 的方法,但存在不会发生注入的限制;请注意,此限制有时是一个实际优势,因为其他一些框架可能会解决注入或以其他方式实例化和更改实例,您只需将其传递给 CDI(例如 - 与 EJB 集成)。

作为一种解决方案,删除生产者并让 CDI 自行创建实例。 CDI 将调用无参数构造函数(或具有可注入参数的构造函数,如果存在)来创建实例并然后对这个新对象执行注入。

从那时起,您的代码应该可以按照您的预期工作。

在极少数情况下,您不能让 CDI 管理整个生命周期并且实际上需要手动创建实例并仍然注入其中,InjectionTargetFactory 是您正在寻找的。它需要一个但 BeanManager.getInjectionTargetFactory() 是您的起点需要。

【讨论】:

  • 感谢您的回答和良好的解释。就像建议的那样,我调整了 Some/OtherImpl 以在没有参数化构造函数的情况下工作,并从控制器中删除了 @Produces 方法。这解决了问题。
  • 解释得很好,真的很有帮助!
猜你喜欢
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 2022-10-12
  • 2014-03-04
  • 2015-04-08
  • 2018-07-13
相关资源
最近更新 更多