自动装配 class 方法的空指针异常
Null pointer exception for autowired class method
我是 Apache Camel 的新手,正在尝试构建 api。它有三个 classes.
Class A - 这是为了读取 application.properties 文件,如下所示
@Configuration
@ConfigurationProperties(prefix="api")
public class A{
private String username;
public String getUsername(){
return username
}
Class B - Apache 骆驼路线。
Class C - Bean class 其中 class A 是自动装配的。
@Component
public class b extends RouteBuilder{
@Autowired
ClassC customC;
public void configure{
from("direct:start")
.bean(customC)
.to("log:first-timer")
}
}
@Component
class C{
@Autowired
ClassA config;
String username=config.getUsername();
}
每当 IDE 执行 api 时,它会在行 String username=config.getUsername();
中抛出空指针异常。我已经验证 spring 引导能够加载 application.properties.
我不确定为什么调用自动装配的方法 class 会抛出空指针异常。
问题出在你的 C
class.
@Component
class C{
@Autowired
A config;
String username = config.gtUsername();
}
Spring初始化的顺序是这样的:
- 创建
C
的实例
(通过调用 new C()
)
此构造函数调用 username = config.gtUsername()
并以 NullPointerException
失败,因为 config
仍然是 null
.
- 处理
@Autowired
(初始化你的config
属性)
但是当然它并没有走到这一步,因为异常已经在步骤 1 中发生了。
您可以通过删除 username
的初始化来解决此问题
属性 来自构造函数,而是将其放入单独的方法中
(我们称它为 init()
)并用 @PostConstruct
注释它。
另见 Spring PostConstruct and PreDestroy Annotations.
@Component
class C{
@Autowired
A config;
String username;
@PostConstruct
void init() {
username = config.getUsername();
}
}
那么Spring初始化的顺序是这样的:
- 创建一个
C
实例
(通过调用 new C()
)
- 处理
@Autowired
.
(这会初始化你的 config
属性)
- 调用
@PostConstruct
-注释方法。
(这会使用已经初始化的 config
属性 初始化您的 username
属性)
解决问题的另一种更简单的方法是使用构造函数
注入(正如@Ferry 已经在他的评论中建议的那样):
不再依赖隐式默认构造函数,
你提供了一个 @Autowired
注释的构造函数,它
可以采用 A config
参数。
此外:这样做,您将不需要
A config
属性 了。
@Component
class C{
String username;
@Autowired
C(A config) {
username = config.getUsername();
}
}
那么Spring初始化的顺序是这样的:
- 处理
@Autowired
(通过调用 new C(config)
创建 C
的实例,其中 config
是先前在自动装配过程中创建的 A
实例)
这使用构造函数接收的 config
初始化您的 username
属性。
我是 Apache Camel 的新手,正在尝试构建 api。它有三个 classes.
Class A - 这是为了读取 application.properties 文件,如下所示
@Configuration
@ConfigurationProperties(prefix="api")
public class A{
private String username;
public String getUsername(){
return username
}
Class B - Apache 骆驼路线。
Class C - Bean class 其中 class A 是自动装配的。
@Component
public class b extends RouteBuilder{
@Autowired
ClassC customC;
public void configure{
from("direct:start")
.bean(customC)
.to("log:first-timer")
}
}
@Component
class C{
@Autowired
ClassA config;
String username=config.getUsername();
}
每当 IDE 执行 api 时,它会在行 String username=config.getUsername();
中抛出空指针异常。我已经验证 spring 引导能够加载 application.properties.
我不确定为什么调用自动装配的方法 class 会抛出空指针异常。
问题出在你的 C
class.
@Component
class C{
@Autowired
A config;
String username = config.gtUsername();
}
Spring初始化的顺序是这样的:
- 创建
C
的实例 (通过调用new C()
)
此构造函数调用username = config.gtUsername()
并以NullPointerException
失败,因为config
仍然是null
. - 处理
@Autowired
(初始化你的config
属性)
但是当然它并没有走到这一步,因为异常已经在步骤 1 中发生了。
您可以通过删除 username
的初始化来解决此问题
属性 来自构造函数,而是将其放入单独的方法中
(我们称它为 init()
)并用 @PostConstruct
注释它。
另见 Spring PostConstruct and PreDestroy Annotations.
@Component
class C{
@Autowired
A config;
String username;
@PostConstruct
void init() {
username = config.getUsername();
}
}
那么Spring初始化的顺序是这样的:
- 创建一个
C
实例
(通过调用new C()
) - 处理
@Autowired
.
(这会初始化你的config
属性) - 调用
@PostConstruct
-注释方法。
(这会使用已经初始化的config
属性 初始化您的username
属性)
解决问题的另一种更简单的方法是使用构造函数 注入(正如@Ferry 已经在他的评论中建议的那样):
不再依赖隐式默认构造函数,
你提供了一个 @Autowired
注释的构造函数,它
可以采用 A config
参数。
此外:这样做,您将不需要
A config
属性 了。
@Component
class C{
String username;
@Autowired
C(A config) {
username = config.getUsername();
}
}
那么Spring初始化的顺序是这样的:
- 处理
@Autowired
(通过调用new C(config)
创建C
的实例,其中config
是先前在自动装配过程中创建的A
实例)
这使用构造函数接收的config
初始化您的username
属性。