spring boot @Value 注解获取不到 properties 或 yml 定义的值
之前也是看过、用过 @Value
来绑定配置文件中定义的属性值的。通过百度完善了部分拼图,除了 @Value
定义属性外,还需要对使用的类添加 @Component
以便类能够被扫描到。
测试用例来自 netty writing-a-discard-server demo:
public class DiscardServer {
private int port;
public DiscardServer(int port) {
this.port = port;
}
...
在 properties 文件里增加 netty.port=8888
,并对类增加相关注解,但在类的构造函数中确是获取不到 @Value
注解的值的:
@Slf4j
@Component
public class DiscardServer {
@Value("${netty.port:8088}")
private int port;
public DiscardServer() {
log.info("netty port:" + port);
}
...
之后因为构造函数获取不到 port
而去怀疑参数定义和方法是否正确,无果。
尝试增加一个配置类,使用配置类来独立设置属性:
@Slf4j
@Component
public class NettyConfig {
@Value("${netty.port:8088}")
private int port;
public NettyConfig() {
log.info("netty config port:" + port);
}
public int getPort(){
return port;
}
}
然后在 DiscardServer
构造函数中调用(去除 DiscardServer
中的 @Value
注解):this->port = new NettyConfig()->getPort();
,结果日志输出依然是 0。
继续百度,找到了一篇针对 @Value
获取值为空的原因分析。对照发现问题:
情况五:类被new新建了实例,而没有使用@Autowired
这是我不知道的,使用 @Autowired
代替 new。
@Autowired
private NettyConfig nettyConfig;
...
public DiscardServer() {
// 方法调用 'getPort' 可能生成 'NullPointerException'
this->port = nettyConfig.getPort();
}
...
有一个警告:方法调用 'getPort' 可能生成 'NullPointerException',忽略去调试结果真的就报这个错了。使用 IDE 的查找原因,结果是找不到。这似乎又是一团乱麻。
回过头来如果直接使用 nettyConfig.getPort()
,可以,这意味着在不适用 NettyConfig 类之前,在非构造函数中直接输出 port
也是可以的。
总结:
@Value
注解值在构造函数中是获取不到,但可以在其他实例方法中直接使用- 当包含
@Value
注解的类实例化时,需要使用@Resource
或者@Autowired
自动装配到调用类,而非 new 实例化 @Autowired
与@Resource
都可以自动装配类,但@Autowired
在使用Spring
框架才有。