java - Autowired Spring Bean 在抽象父类中为空
问题描述
我有一个 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.<init>(MongoDbAccessor.java:26)
线在哪里String databaseName = projectSettings.getMongodbDatabaseName();
现在,我已经确认projectSettings
在这种情况下该字段确实为空。但是,我还能够确认,如果我尝试访问ProjectSettings
bean 中的 bean SomeDataDbEditor
,它会起作用,并且 bean 会被正确实例化。
我知道此时一个可能的解决方案是使用它并将ProjectSettings
bean 手动传递给父类,但这会破坏首先使用依赖注入的意义。此外,我将不得不为此调整,非常非常多的课程,如果可能的话,我想避免这种情况。
那么,有谁知道为什么会在这里发生这种情况,以及我能做些什么呢?
解决方案
如果使用字段注入(Autowired on fields),则不能在构造函数中使用这些字段,因为 Spring 只能在构造对象之后注入依赖项,即在所有构造函数完成之后。
为了避免这种情况,您必须更改为构造函数注入,或者在构造函数中执行的初始化工作,在使用 PostConstruct 注释的单独方法中:
@javax.annotation.PostConstruct
public void initialize() {
}
但是,如果您能够将代码更改为构造函数注入,我(以及 Spring 世界中的许多其他人)强烈推荐它,因为它完全可以防止此类问题。
推荐阅读
- node.js - Node.js 无法查看中间件中的标头
- django-channels - Django 频道:压缩?
- c - ELF 文件的 .dynamic 部分中的 DT_USED 条目
- oracle - ORA-01422: 精确提取返回的行数超过请求的行数 ORA-06512
- crm - Responsys:使用动态路径创建跟踪链接
- java - 更新后使用 Android Studio 创建新项目的问题
- matlab - 将 3D 旋转矩阵应用于从表面函数获得的 x、y、z 值
- python - 用于在 Spyder 中将工作目录设置为源文件位置的 Python 命令
- azure - Azure Cognitives 服务语音到文本的数字实体识别为文本
- excel - 使用 VBA 在 Excel 中插入多个分页符的最快方法