【问题标题】:Autowired Spring Bean is null in abstract parent classAutowired Spring Bean 在抽象父类中为空
【发布时间】:2021-03-03 07:22:39
【问题描述】:

我有一个 Bean,负责从配置文件加载项目设置,并使它们可供任何其他可能需要它们的对象使用:

@Component
public class ProjectSettings extends Settings{[...]}

现在,我有一堆组件类,它们通过多个步骤扩展了一个抽象类,我想在其中使用这个 bean:

@Component
public class SomeDataDbEditor extends MongoDbEditor<SomeData> {[...]}

public abstract class MongoDbEditor<T extends MongodbEntryInterface> extends MongoDbTypedAccessor<T>{[...]}

public abstract class MongoDbTypedAccessor<T extends MongodbEntryInterface> extends MongoDbAccessor {[...]}

public abstract class MongoDbAccessor {
    @Autowired
    protected ProjectSettings projectSettings;

    public MongoDbAccessor() throws DatabaseNotConnectedException {
        String databaseName = projectSettings.getMongodbDatabaseName();
        [...]
}

据我了解,这应该可以工作,因为@Autowired 字段受到保护,因此可以从@Component 类SomeDataDbEditor 中看到。但是,我得到了这个异常:

java.lang.IllegalStateException: Failed to load ApplicationContext
[...]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.company.project.module.some_data.database.accessor.SomeDataDbEditor]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:217)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:310)
    ... 124 more
Caused by: java.lang.NullPointerException
    at io.company.project.module.database.accessor.MongoDbAccessor.<init>(MongoDbAccessor.java:26)
    at io.company.project.module.database.accessor.MongoDbTypedAccessor.<init>(MongoDbTypedAccessor.java:20)
    at io.company.project.module.database.accessor.MongoDbEditor.<init>(MongoDbEditor.java:19)
    at io.company.project.module.some_data.database.accessor.SomeDataDbEditor.<init>(SomeDataDbEditor.java:17)

...引用的MongoDbAccessor.&lt;init&gt;(MongoDbAccessor.java:26) 行是String databaseName = projectSettings.getMongodbDatabaseName();

现在,我已经确认 projectSettings 字段在这种情况下确实为空。但是,我还能够确认,如果我尝试访问 SomeDataDbEditor 中的 ProjectSettings bean,它会起作用,并且 bean 会被正确实例化。

我知道此时一个可能的解决方案是使用它并手动将ProjectSettings bean 传递给父类,但这会破坏首先使用依赖注入的意义。此外,我必须为此调整很多课程,而且我想尽可能避免这种情况。

那么,有没有人知道为什么会发生这种情况,以及我能做些什么来对付它?

【问题讨论】:

    标签: java spring dependency-injection


    【解决方案1】:

    如果使用字段注入(Autowired on fields),则不能在构造函数中使用这些字段,因为 Spring 只能在构造对象后(即所有构造函数完成后)注入依赖项。

    为了避免这种情况,您必须更改为构造函数注入,或者在使用 PostConstruct 注释的单独方法中执行您在构造函数中所做的初始化工作:

    @javax.annotation.PostConstruct
    public void initialize() {
    
    }
    

    但是,如果您能够将代码更改为构造函数注入,我(以及 Spring 世界中的许多其他人)强烈推荐它,因为它可以防止此类问题。

    【讨论】:

      猜你喜欢
      • 2020-11-04
      • 2017-03-14
      • 2022-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多