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()
是你需要的起点。
我正在尝试将依赖项注入 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()
是你需要的起点。