@Value的用法

目录

前言

1 从一个例子开始

2 @Value注解的默认值

3 通过@Value注入static 类型的属性

 4 @Value支持的注入类型

4.1基本类型

4.2数组

4.3 集合类

4.3.1 List

4.3.2 Map

4.3.3 Set

4.3.4  时间类型属性

 4.3.5  获取系统属性

4.4注入Bean

 4.5调用静态类

5 ${}和#{}的区别

5.1  ${}

5.2 #{}

6 项目结构


前言

如果想要动态读取配置文件中的某个系统属性,可以使用@Value注解

1 从一个例子开始

假如在Person类中,需要注入系统属性到name变量中。通常情况下,我们会写出如下的代码:

@Component
public class Person {
    @Value("${person.name}")
    private String name;
    /*setter and getter */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

通过@Value注解指定系统属性的名称person.name,该名称需要使用${}包起来。

这样spring就会自动的帮我们把对应的系统属性值,注入到name变量中。

不过,上面功能的重点是要在application.properties文件(简称:配置文件)中配置同名的系统属性:
 

person.name=liname

那么,使用@Value注解时的属性名必须与配置文件属性名一致吗?

是的,如果不一致启动时直接报错。

2 @Value注解的默认值

比如有这样一个需求:如果配置了系统属性,name就用配置的属性值。如果没有配置,则name用默认值lisa。

有些朋友可能认为可以这样做:

applicaiton.properties

#person.name=li
@Component
public class Person {
    @Value("${person.name}")
    private String name="lisa";
    /*setter and getter */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

结果是启动报错

@Value的用法_第1张图片

 也就是在定义参数时直接给个默认值是行不通的的。因为设置name默认值的时机,比@Value注解依赖注入属性值要早,也就是说name初始化好了默认值,后面还是会读取person.name的值。

那么,到底该如何设置默认值呢?

答:使用 :

例如:

@Component
public class Person {
    @Value("${person.name:lisa}")
    private String name;
    /*setter and getter */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在需要设置默认值的系统属性名后,加 : 符号。紧接着,在 : 右边设置默认值。

建议大家平时在使用@Value时,尽量都设置一个默认值。如果不需要默认值,宁可设置一个空。比如:

@Component
public class Person {
    @Value("${person.name:}")
    private String name;
    /*setter and getter */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Value的用法_第2张图片

这样的话,如果不在.properties文件中配置同名的系统属性,则服务启动时也就不会报错

3 通过@Value注入static 类型的属性

前面我们已经见识过,如何使用@Value注解,给类的成员变量注入系统属性值。

那么,问题来了,静态变量可以自动注入系统属性值不?

增加一个静态属性检验一下

@Component
public class Person {

    @Value("${person.name:}")
    private String name;

    @Value("${person.staticpro:aa}")
    public static String staticpro;
}

application.properties

person.name=liq
person.staticpro=staticproValue

运行结果

@Value的用法_第3张图片

程序可以正常启动,但是获取到的值却是null。

由此可见,被static修饰的变量通过@Value会注入失败。

如何才能给静态变量注入系统属性值呢?

操作如下:

@Component
public class Person {
    @Value("${person.name:}")
    private String name;

    @Value("${person.staticpro:aa}")
    public static String staticpro;
    
    @Value("${person.staticpro:aa}")
    public  void setStaticpro(String staticpro) {
        Person.staticpro = staticpro;
    }
    public static String getStaticpro() {
        return staticpro;
    }

    /*setter and getter */
}

application.properties

person.name=liq
person.staticpro=staticproValue

提供一个静态参数的setter方法,在该方法上使用@Value注入属性值,并且同时在该方法中给静态变量赋值。

此时@Value注解在这里竟然使用在setStaticpro方法上了,也就是对应的setter方法,而不是在变量上。

不过,通常情况下,我们一般会在pojo实体类上,使用lombok的@Data、@Setter、@Getter等注解,在编译时动态增加setter或getter方法,所以@Value用在方法上的场景其实不多

运行结果

@Value的用法_第4张图片

 4 @Value支持的注入类型

上面的内容,都是用的字符串类型的变量进行举例的。其实,@Value注解还支持其他多种类型的系统属性值的注入。

4.1基本类型

Java中的基本数据类型有4类8种

整型:byte、short、int、long
浮点型:float、double
布尔型:boolean
字符型:char
相对应地提供了8种包装类:

整型:Byte、Short、Integer、Long
浮点型:Float、Double
布尔型:Boolean
字符型:Character
@Value注解对这8中基本类型和相应的包装类,有非常良好的支持,例如:
 

@Component
public class Person {
    @Value("${person.name:}")
    private String name;
    @Value("${person.staticpro:aa}")
    public static String staticpro;
    @Value("${person.a:1}")
    private byte a;
    @Value("${person.b:100}")
    private short b;
    @Value("${person.c:1000}")
    private int c;
    @Value("${person.d:40000000}")
    private long d;
    @Value("${person.e:5.2}")
    private float e;
    @Value("${person.f:6.1}")
    private double f;
    @Value("${person.g:false}")
    private boolean g;
    @Value("${person.h:h}")
    private char h;
    @Value("${person.a}")
    private Byte a1;
    @Value("${person.b}")
    private Short b1;
    @Value("${person.c}")
    private Integer c1;
    @Value("${person.d}")
    private Long d1;
    @Value("${person.e}")
    private Float e1;
    @Value("${person.f}")
    private Double f1;
    @Value("${person.g}")
    private Boolean g1;
    @Value("${person.h}")
    private Character h1;
/* setter and getter*/
}

有了这些常用的数据类型,我们在定义变量类型时,可以非常愉快的使用了,不用做额外的转换。

4.2数组

定义一个数组属性

@Component
public class Person {
    @Value("${person.name:}")
    private String name;
    @Value("${person.staticpro:aa}")
    public static String staticpro;

    @Value("${person.hobbiess}")
    private String[] hobbiess;

    /*setter and getter */
}

application.properties

person.name=liq
person.staticpro=staticproValue
person.hobbiess=game,tv,sing

运行结果

@Value的用法_第5张图片

 spring默认使用逗号分隔参数值。

如果用空格分隔,例如:

application.properties

person.name=liq
person.staticpro=staticproValue
person.hobbiess=game tv sing

那么spring认为只有一个值

@Value的用法_第6张图片

 如果非要用非逗号做分割,比如上面用空格做分割,那么可以在@Value时使用表达式

@Value的用法_第7张图片

4.3 集合类

4.3.1 List

定义一个List类型的属性

@Component
public class Person {
    @Value("${person.name:}")
    private String name;
    @Value("${person.staticpro:aa}")
    public static String staticpro;

    //@Value("${person.hobbiess}")
    @Value("#{'${person.hobbiess}'.split(' ')}")
    private String[] hobbiess;

    //注意sprlit()方法的分割类型要与application.properties中list用的分割类型一致。
    @Value("#{'${person.list}'.split(' ')}")
    private List list;

 /*setter and getter */
}

application.properties

person.name=liq
person.staticpro=staticproValue
person.hobbiess=game tv sing
person.list=basketball tennis swim

测试结果

@Value的用法_第8张图片

4.3.2 Map

定义一个Map类型的属性

@Component
public class Person {
    @Value("${person.name:}")
    private String name;
    @Value("${person.staticpro:aa}")
    public static String staticpro;

    //@Value("${person.hobbiess}")
    @Value("#{'${person.hobbiess}'.split(' ')}")
    private String[] hobbiess;
    //注意sprlit()方法的分割类型要与application.properties中list用的分割类型一致。
    @Value("#{'${person.list}'.split(' ')}")
    private List list;

    @Value("#{${person.map}}")
    private Map map;


    /*setter and getter */
}

application.properties

person.name=liq
person.staticpro=staticproValue
person.hobbiess=game tv sing
person.list=basketball tennis swim
person.map={aa:"aa",bb:"bb"}

测试结果

@Value的用法_第9张图片

4.3.3 Set

Set和List极为相似,不在赘述。这里说一下@Value如何为list和Map注入默认值

List属性注入默认值:

@Value的用法_第10张图片

@Value的用法_第11张图片

@Value的用法_第12张图片

@Value的用法_第13张图片

 @Value的用法_第14张图片

测试默认值

@Value的用法_第15张图片

4.3.4  时间类型属性

@Value的用法_第16张图片@Value的用法_第17张图片

 4.3.5  获取系统属性

@Value的用法_第18张图片

4.4注入Bean

以前我们注入bean,一般都是用的@Autowired或者@Resource注解。例如:

@Value的用法_第19张图片

用@Value注解也可以注入bean,举例如下:

@Value的用法_第20张图片

@Value的用法_第21张图片

@Value的用法_第22张图片

 @Value的用法_第23张图片

 4.5调用静态类

@Value的用法_第24张图片

 @Value的用法_第25张图片

5 ${}和#{}的区别

5.1  ${}


${}主要用于获取配置文件中的系统属性值。

例如:

@Value(value = "${person.name}")
private String name;
可以设置默认值。如果在配置文件中找不到person.name的配置,则注入时用默认值。

如果在配置文件中找不到person.name的配置,也没有设置默认值,则启动项目时会报错

@Value的用法_第26张图片

 @Value的用法_第27张图片

 

5.2 #{}

#{}主要用于通过spring的EL表达式,获取bean的属性,或者调用bean的某个方法。还有调用类的静态常量和静态方法。

6 项目结构

maven项目POM


    4.0.0

    org.XX
    LearnSpringBoot2-javaproject
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.4.RELEASE
    
    

    
    
        org.springframework.boot
        spring-boot-starter
    
        
            org.springframework.boot
            spring-boot-configuration-processor
        
    
    
        8
        8
        UTF-8
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

项目目录结构

@Value的用法_第28张图片

 将application.properties换成application.yml 结果一样

person:
  age: 27
  name: scy
  staticpro: staticproValue
  hobbiess: game,tv,sing
  list:
          basketball
          tennis
          swim
  map: '{ aa: "aaa",bb: "bbb"}'
  birthday: 2022-01-07 12:12:12

address:
      province: 某某省
      distinct: 某某市
      county: 某某县

你可能感兴趣的:(开发语言)