@Value不生效原因排查
问题代码区域
在@Configuration+@Bean实现注入bean对象里面调用注入的@Value标识的值。
@Configuration
public class InitRedisConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private Integer redisPort;
@Value("${spring.redis.database}")
private Integer redisDatabase;
/**
* 所有对Redisson的使用都是通过RedissonClient对象
* @return
*/
@Bean(destroyMethod = "shutdown")
public RedissonClient redissonClient(){
// 创建配置 指定redis地址及节点信息
Config config = new Config();
String redisAddr = "redis://" + redisHost + ":" + redisPort;
config.useSingleServer()
.setAddress(redisAddr)
.setPassword(null)
.setDatabase(redisDatabase);
// 根据config创建出RedissonClient实例
return Redisson.create(config);
}
}
错误日志
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.redis.host' in value "${spring.redis.host}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) ~[spring-core-5.3.16.jar:5.3.16]
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-5.3.16.jar:5.3.16]
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239) ~[spring-core-5.3.16.jar:5.3.16]
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-5.3.16.jar:5.3.16]
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:191) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:936) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1330) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.16.jar:5.3.16]
... 40 common frames omitted
spring中核心类的注入顺序
源码
@Value注入的后置处理器:AutowiredAnnotationBeanPostProcessor
注入的位置:
可以看出来AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition方法是在上面步骤中的第四步执行,会在其中扫描@Value注解,并且会将注解标识的bean注入。
@Configuration+@Bean注入的后置处理器:ConfigurationClassPostProcessor
可以看出来ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry方法是在上面步骤中的第一步执行,会在其中扫描@Bean注解,并且会将注解标识的bean注入。
分析
-
@Value这个注解并没有失效,属性值仍然会注入到变量中。
-
@Value注入的值无法读取,主要还是在于@Value注入的值顺序在@Configuration+@Bean的后面,所以才会出现读取到的@Value标记的值为null。
-
如果不是@Value,而是使用@Autowired去注入,那么由于顺序问题,效果也是一样的。