@Value注解不能注入static修饰的属性

1:问题描述

配置文件application.yml:

person.name: nobody
person.age: 20

实体类Person:

package com.nobody.pojo.entity;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = -8245392957106320519L;

    @Value("${person.name}")
    private static String name;
    
    private static String age;
    
    @Value("${person.age}")
    public void setAge(String age) {
        Person.age = age;
    }
    
    public void setName(String name) {
        Person.name = name;
    }
    
    public static String getName() {
        return name;
    }
    
    public static String getAge() {
        return age;
    }

}

测试接口类DemoController:

package com.nobody.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.nobody.ehr.pojo.entity.Person;

@RequestMapping("demo")
@RestController
public class DemoController {
    
    @GetMapping
    public String demo() {
        
        System.out.println("name:" + Person.getName() + ", age:" + Person.getAge());
        
        return "";
    }

}

测试结果:
@Value注解放在属性上注入值失败,而@Value放在setter方法上(注意,该方法也不能是静态方法)注入成功。

name:null, age:20

2:分析

启动日志:

[19:37:45] INFO  [restartedMain] o.s.b.f.a.AutowiredAnnotationBeanPostProcessor 
			    - Autowired annotation is not supported on static fields: private static java.lang.String com.nobody.pojo.entity.Person.name

源码分析:

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) {
          //这里对静态属性注入做了过滤
					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))) {
          //这里对静态方法做了过滤
					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);
	}

3:结论

从源码上发现,理论上spring是可以对静态域注入的,只是spring没有这样做,它认为依赖注入发生的时段是在实例的生命周期,而不是类的生命周期。

猜你喜欢

转载自blog.csdn.net/chenlixiao007/article/details/105229998
今日推荐