Spring

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

2020-07-16  本文已影响0人  AbstractCulture

在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修饰符的成员变量进行注入.

/**
     * 解析当前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静态成员?官方不推荐你却还偏要这么做

上一篇 下一篇

猜你喜欢

热点阅读