美文网首页Spring
工具类使用@Value将信息注入到静态变量中

工具类使用@Value将信息注入到静态变量中

作者: AbstractCulture | 来源:发表于2020-07-16 17:52 被阅读0次

    在spring工程中,我们经常需要使用到配置文件的一些信息,在每个类中定义,可能导致这些信息变得零散。spring给我们提供了一个注解@Value(),使我们可以注入配置文件中的数据。

    bootstrap.yml

     jay:
        key: www.baidu.com
    

    如果你想在你的工具类中注入这个变量,那么你可能面临问题,方法是static的,那么你需要使用静态变量作为参数在方法中使用。

    错误示范:

    public class testUtils{
           @Value("${jay.key}")
           private static String url;
    }
    
    

    正确示范

    @Configuration
    public class testUtils{
        private static String url;
    
        @Value("${jay.key}")
        public void setUrl(String url) {
            url= url;
        }
    }
    
    

    通过@Component和在Setter上打上注解,即可将配置文件的信息注入到静态变量中了.

    为什么会出现空指针?

    先说结论: Spring从源码层面不提供对static修饰符的成员变量进行注入.

    • AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
    /**
         * 解析当前Class被@Autowired标记的成员
         * @param clazz
         * @return
         */
        private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
            List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
            Class<?> targetClass = clazz;
            // 递归遍历当前类及其所有基类,解析全部注解元信息
            do {
                final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
                // 收集被@Autowired、@Value标记的Field.
                // 利用反射机制获取给定类中所有的声明字段,获取字段上的注解信息
                // doWithLocalFields->获取当前类的所有Field,每个field执行lambda内的逻辑.
                ReflectionUtils.doWithLocalFields(targetClass, field -> {
                    // 此处逻辑较为复杂,通过debug发现如果为被标注的属性,会返回required:true.
                    // 大致的意思是这个field是否被特定的注解标记?这里留一个疑问
                    AnnotationAttributes ann = findAutowiredAnnotation(field);
                    if (ann != null) {
                        // 如果是static属性的成员,Spring不提供支持
                        if (Modifier.isStatic(field.getModifiers())) {
                            if (logger.isInfoEnabled()) {
                                logger.info("Autowired annotation is not supported on static fields: " + field);
                            }
                            return;
                        }
                        // 判断required的状态
                        boolean required = determineRequiredStatus(ann);
                        // 将当前成员添加进currElements
                        currElements.add(new AutowiredFieldElement(field, required));
                    }
                });
        // 省略....
        }
    

    static的变量是归属于Class的,而Spring容器上下文只对Java对象进行管理,Spring不鼓励对static变量做注入Bean的操作,因此如果需要在某些工具类中将Bean赋值给静态变量,可以使用构造注入的方式. 或者使用@PostConstruct作为桥梁.
    想深入的朋友可以看看这篇文章: 想用@Autowired注入static静态成员?官方不推荐你却还偏要这么做

    相关文章

      网友评论

        本文标题:工具类使用@Value将信息注入到静态变量中

        本文链接:https://www.haomeiwen.com/subject/sskmhktx.html