cdi 注入的依赖项在生产者方法创建的 bean 中解析为 null

cdi injected dependency resolved to null in a bean created by a producer method

我正在尝试将依赖项注入 bean (Some/OtherImpl),用 @Named 注释,但依赖项 (configurationService) 总是解析为 null ( Resources#getConfiguratioService 未调用)当使用其生产者方法在控制器 (MyCtrl) 中创建该 bean 的新实例时。

但是,如果我尝试将 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 关键字创建 SomeImpl 'manually' 的实例。 在这种情况下,您create/provide对象,不注入,你把这个对象交给CDI。从那时起,任何类型为 SomeImpl 且具有默认限定符的注入点都将使用您的生产者来创建 bean。生产者通常是一种将非 CDI 对象转换为 CDI bean 的方法,但存在注入不会发生的限制;请注意,此限制有时是一个实际优势,因为某些其他框架可能会解析注入或以其他方式实例化并更改实例,您只需将其传递给 CDI(示例 - 与 EJB 集成)。

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

从那时起,您的代码应该会像您期望的那样工作。

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