您现在的位置是:群英 > 开发技术 > 编程语言
@Value注解不能注入static属性怎么办呢?
Admin发表于 2022-10-11 09:22:57752 次浏览
这篇文章主要给大家介绍“@Value注解不能注入static属性怎么办呢?”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“@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属性怎么办呢?”的内容就介绍到这,感谢各位的阅读,相信大家对@Value注解不能注入static属性怎么办呢?已经有了进一步的了解。大家如果还想学习更多知识,欢迎关注群英网络,小编将为大家输出更多高质量的实用文章!

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

相关信息推荐
2022-05-13 17:50:16 
摘要:在PHP中,time是“时间”的意思,是PHP中的一个内置函数,用于返回Unix纪元起到当前时间秒数的函数,返回的结果是一个包含当前时间Unix时间戳的整数,该函数没有参数,语法为“time()”。
2022-09-15 17:48:31 
摘要:本篇文章给大家带来了关于Java的相关知识,其中主要介绍了关于set集合的相关问题,set集合的特点是无序、不重复并且没有索引,下面一起来看一下,希望对大家有帮助。
2022-08-25 17:53:08 
摘要:这篇文章主要给大家介绍了关于Laravel中如何轻松容易的输出完整的SQL语句的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Laravel具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部