源码地址:https://github.com/nieandsun/spring-study

1 @Value使用简介

1.1 简单入门

比如有下面一个类,可以利用@Value给其进行赋值

package com.nrsc.springstudy.c09_Value.beans;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;

@Getter
@Setter
@ToString
public class Dog {
    @Value("李四") 
    private String name;

    @Value("#{20-2}") //SpringEl表达式
    private Integer age; 

    private String color;
}

程序启动可以发现该对象的name和age已经被附上值了:
【bean的生命周期 - spring注解】@Value_Spring


1.2 利用@Value读取配置文件中的值并赋值给类的属性

(1)首先建立一个配置文件
【bean的生命周期 - spring注解】@Value_spring_02
(2)在配置类中读取配置文件

package com.nrsc.springstudy.c09_Value.config;

import com.nrsc.springstudy.c09_Value.beans.Cup;
import com.nrsc.springstudy.c09_Value.beans.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@PropertySource(value = {"classpath:/Test09Value.properties"}) //读取配置文件
@Configuration
public class C09Config {
    @Bean
    public Dog dog() {
        return new Dog();
    }

    @Bean
    public Cup cup() {
        return new Cup();
    }
}

(3)写测试类

package com.nrsc.springstudy.c09_Value.beans;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;

/**
 * @author : Sun Chuan
 * @date : 2019/11/24 19:56
 * Description:
 */
@Setter
@Getter
@ToString
public class Cup {
    /***
     * 直接从配置文件里读取配置内容赋值给当前属性
     */
    @Value("${cup.name}")
    private String name;

    /***
     * 通过SpringEl表达式获取dog的age值赋值给当前属性
     */
    @Value("#{dog.age}")
    private Integer size;

    /***
     * 通过SpringEl表达式获取dog的color值赋值给当前属性,如果color的值为空,则将white赋值给当前属性
     */
    @Value("#{dog.color?:'white'}")
    private String color;
}

测试结果如下,可以看到Cup中已经被设置了正确的值。
【bean的生命周期 - spring注解】@Value_Spring_03

2 一些小细节 — 简单提一下

(1)@Value注解的作用时机在populateBean(beanName, mbd, instanceWrapper)方法内;
(2)处理该注解的后置处理器(BeanPostProcessor)为AutowiredAnnotationBeanPostProcessor


了解了上面两条之后,就可以将《【bean的生命周期】— 构造方法、@Autowired、BeanPostProcessor、InitializingBean等的执行顺序解析》那篇文章里所展示的构造方法、@Autowired、BeanPostProcessor、InitializingBean等的执行顺序图,加上@Value之后画成下面的样子:

【bean的生命周期 - spring注解】@Value_Spring_04


(3)@Value注解不止可以放在属性字段上,还可以放在方法、参数和注解中,其源码如下:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {

	/**
	 * The actual value expression: e.g. "#{systemProperties.myProp}".
	 */
	String value();

}

(4)实际开发中可能会很少用这个注解,我现在已经要求我们项目里全部使用我之前介绍的一种方式 — 《springboot项目真实开发中如何通过yml或properties文件向项目中传值》来处理配置信息。

(5)properties被加载到了哪里??? —> 答案为环境变量里,下面做一个简单的测试

  • 测试代码
import com.nrsc.springstudy.c09_Value.beans.Cup;
import com.nrsc.springstudy.c09_Value.beans.Dog;
import com.nrsc.springstudy.c09_Value.config.C09Config;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

/**
 * @author : Sun Chuan
 * @date : 2019/11/24 19:51
 * Description:
 */
public class Test09_Value {

    @Test
    public void test01() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(C09Config.class);
        Dog dog = (Dog) ac.getBean("dog");
        Cup cup = (Cup) ac.getBean("cup");

        System.err.println("====dog====" + dog);
        System.err.println("====cup====" + cup);
        
        //简单测试properties文件被加载到了哪里
        ConfigurableEnvironment environment = ac.getEnvironment();
        System.err.println("environment===" + environment.getProperty("cup.name"));
        System.out.println("IOC容器创建完成........");
    }
}
  • 测试结果如下,可以发现从环境变量里获取到了我配置的cup.name的值 —> BigCup

【bean的生命周期 - spring注解】@Value_spring的@Value注解_05