这篇文章主要介绍了解决@Value注解不能注入static修饰的属性问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
@Value注解不能注入static属性
问题描述
在application.yml中:
constant:
key: hello
value: world
工具类ConstantHelper:
@Component
public class ConstantHelper {
@Value("${constant.value}")
private static String value;
private static String key;
public static String getValue() {
return value;
}
public void setValue(String value) {
ConstantHelper.value = value;
}
public static String getKey() {
return key;
}
@Value("${constant.key}")
public void setKey(String key) {
ConstantHelper.key = key;
}
}
测试类:
@RequestMapping("/getConfig")
public Map<String, Object> getConfig(){
Map<String,Object> map = new HashMap<>();
map.put("key", ConstantHelper.getKey());
map.put("value",ConstantHelper.getValue());
return map;
}
结果:
{
"value": null,
"key": "hello"
}
可以发现,@Value注解放在属性上注入值失败,而@Value放在setter方法上(注意,该方法也不能是静态方法)却能注入成功。为什么??
剖析
答案就在AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata方法中,AutowiredAnnotationBeanPostProcessor主要处理了@Autowired和@Value注解等等:
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
//here!!
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//here!!
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
The conceptual problem here is that annotation-driven injection happens for each bean instance. So we shouldn’t inject static fields or static methods there because that would happen for every instance of that class. The injection lifecycle is tied to the instance lifecycle, not to the class lifecycle. Bridging between an instance’s state and static accessor - if really desired - is up to the concrete bean implementation but arguably shouldn’t be done by the framework itself.
从源码上发现,理论上spring是可以对静态域注入的,只是spring没有这样做,它认为依赖注入发生的时段是在实例的生命周期,而不是类的生命周期
@Value(“${属性}“)注入被static修饰的属性
场景:
通过httpclient调用第三方接口的时候,ip和端口不确定
需求:
写一个工具类,可以动态配置ip和端口来修改调用的地址和端口,要求工具类方法可以静态调用。
问题描述
static 不能和注解并用,被static修饰的成员变量,无法通过@Value注解动态获取到
解决方案
通过注入到set方法实现属性动态赋值
application.yml配置:
key:
box:
ip: 192.168.1.166
port: 9987
错误代码:
@Value("${key.box.ip}")
private static String ip ;
@Value("${key.box.port}")
private static String port;
这样写的话,你会发现拿到的结果还是null
正确代码:
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* Created in 2021/6/29 15:07
* @author
*/
@Slf4j
@Component
public class KeyBoxHttpClientUtil {
private static String ip ;
private static String port;
@Value("${key.box.ip}")
public void setIP(String ip) {
KeyBoxHttpClientUtil.ip = ip;
}
@Value("${key.box.port}")
public void setPort(String port) {
KeyBoxHttpClientUtil.port = port;
}
}
Tips:调整代码之后,工具类必须使用@Component注解来修饰,否则依然无法获取到结果。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程学习网。
本文标题为:解决@Value注解不能注入static修饰的属性问题
基础教程推荐
- Java并发编程进阶之线程控制篇 2023-03-07
- Java实现线程插队的示例代码 2022-09-03
- java实现多人聊天系统 2023-05-19
- springboot自定义starter方法及注解实例 2023-03-31
- Java数据结构之对象比较详解 2023-03-07
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java实现查找文件和替换文件内容 2023-04-06
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- java基础知识之FileInputStream流的使用 2023-08-11
- Java文件管理操作的知识点整理 2023-05-19