尝试在构造函数中访问 @Inject bean 时出现 NullPointerException

Posted

技术标签:

【中文标题】尝试在构造函数中访问 @Inject bean 时出现 NullPointerException【英文标题】:NullPointerException while trying to access @Inject bean in constructor 【发布时间】:2013-04-30 06:44:35 【问题描述】:

我有一个会话范围的 bean:

@Named
@SessionScoped
public class SessionBean implements Serializable 

    private String someProperty;

    public String getSomeProperty() 
        return someProperty;
    


我想将它注入到请求范围的 bean 中并用它进行初始化:

@Named
@RequestScoped
public class RequestBean 

    @Inject
    private SessionBean sessionBean;  

    public RequestBean() 
        System.out.println(sessionBean.getProperty());
    


但是,它会引发以下异常:

java.lang.NullPointerException
    at com.example.RequestBean.<init>(RequestBean.java:42)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at org.jboss.weld.introspector.jlr.WeldConstructorImpl.newInstance(WeldConstructorImpl.java:206)
    at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117)
    at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:336)
    at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200)
    at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:292)
    ...

这是怎么引起的,我该如何解决?

【问题讨论】:

只有在实例化完成后才能注入依赖项,但您在构造函数中使用它。尝试在构建后执行代码。 我相信您没有理解“构建后”部分。您应该使用 @PostConstruct 方法,并且绝对不要从构造函数内部调用它。 【参考方案1】:

您期望注入的依赖项在构建 bean 之前可用。你期望它像这样工作:

RequestBean requestBean;
requestBean.sessionBean = sessionBean; // Injection.
requestBean = new RequestBean(); // Constructor invoked.

然而,这不是真的,而且在技术上是不可能的。依赖项是在 构造之后注入的。

RequestBean requestBean;
requestBean = new RequestBean(); // Constructor invoked.
requestBean.sessionBean = sessionBean; // Injection.

如果您打算在 bean 构建后直接基于注入的依赖项执行业务逻辑,则应该使用 @PostConstruct 方法。

移除构造函数并添加此方法:

@PostConstruct
public void init() 
    System.out.println(sessionBean.getSomeProperty());

【讨论】:

我编辑了问题,尝试使用 PostConstruct,结果还是一样。 您仍在使用构造函数。去掉它。重新阅读答案的第一部分。我还建议在继续使用 JSF 之前暂停 JSF 并 learn some basic Java。【参考方案2】:

BalusC 的回复是正确的,但它确实反映了对象创建的分配阶段,此时没有运行。但是无论如何CDI bean 应该可以通过grep 以编程方式访问它:

javax.enterprise.inject.spi.CDI.current().select(SessionBean.class).get()

【讨论】:

以上是关于尝试在构造函数中访问 @Inject bean 时出现 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

在JSF托管bean的构造函数中访问会话bean数据

在托管 bean 构造函数中访问注入的依赖项会导致 NullPointerException

Dagger 2 错误:依赖“不能在没有 @Inject 构造函数的情况下提供”,而它实际上是用 @Inject 注释的

多次调用 JSF Backing Bean 构造函数

Android--Dagger2入门

Kotlin + Dagger2:不能在没有 @Inject 构造函数或 @Provides- 或 @Produces-annotated 方法的情况下提供