以前配bean标签的时候,我们要为哪一个组件配置对象,2我写一个person类型,包括配置的属性值是多少,
<bean class="person">
<property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
</bean>
我写一个property这个标签,我们用name属性来赋值lastName,value就是指定值了,而这一块的value,和我们的@Value注解
是一样的,@Component注解的作用,也是把Person加入到容器中,bean标签也是加入到容器中,而这是一个value赋值,而这里
是使用@Value注解来赋值,比如我们写字面量,以前写字符串数字,布尔值都能写,包括还能写,${key},他的作用呢,是从环境变量,
或者我们也叫配置文件,获取值,这是他的第二种写法,第三种它还支持#{SpEL},Spring的表达式语言,他支持这几个,那我们@Value
里面也是支持这几个,比如我要获取配置文件中lastName,
//@Value("${person.last-name}")
private String lastName;
@Value("#{10*2}")
private Integer age;
这是我们Spring的表达式
然后还有布尔值,我就那这三个属性来测一测
@Value("true")
private Boolean boss;
package com.learn.bean;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中的相关的配置进行绑定
* prefix="person":配置文件中哪个下面的所有属性进行映射
*
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
* 默认从全局配置文件中获取值;
*/
//@PropertySource(value= {"classpath:person.properties"})
@Component
//@ConfigurationProperties(prefix="person")
//@Validated
public class Person {
/**
* <bean class="person">
* <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
* </bean>
*/
// lastName必须是邮箱格式
//@Email
@Value("${person.last-name}")
private String lastName;
@Value("#{10*2}")
private Integer age;
@Value("true")
private Boolean boss;
private Date birth;
//@Value("${person.maps}")
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person [lastName=" + lastName + ", age=" + age + ", boss=" + boss + ", birth=" + birth + ", maps="
+ maps + ", lists=" + lists + ", dog=" + dog + "]";
}
}
package com.learn.springboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.learn.bean.Person;
/**
* SpringBoot单元测试
*
* 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot02ConfigurationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
Person [lastName=张三, age=20, boss=true, birth=null, maps=null, lists=null, dog=null]
22是算出来没问题,true也没问题,但是跟ConfigurationProperties,有没有区别,首先我们ConfigurationProperties只需要
一个注解,批量给我们注入,@Value要一个一个来注入,那我们把这些区别都放到这,一个是@ConfigurationProperties,
这个注解和@Value,他来获取值的区别,首先我们在功能上,@ConfigurationProperties(他可以批量注入我们的配置文件中的
属性,我们只需要指定一个properties就行了,@Value需要一个一个指定,@ConfigurationProperties他还支持一个松散绑定,
也就是松散语法,这个松散语法的意思就是说,特别是last-name,我们有一个属性名叫lastName,驼峰命名法的,那你用中间的
杠,大小写不区分,下划线,都是可以的,这是我们松散绑定
但是只有@ConfigurationProperties能够支持,如果我们把Value指成lastName
@Value("${person.lastName}")
由于我们配置文件里面是
person.last-name=\u5F20\u4E09
我们来看能不能支持,我们发现就启动报错了,说我们peron.last-name获取值有问题,所以我们必须是last-name,
他不支持松散语法绑定,而我们这个@ConfigurationProperties呢,他支持,用@ConfigurationProperties获取值,我们lastName
是能获取到值的,我们这一块你写last-name,还是lastName,这都没问题,人家支持松散语法绑定,这就是我们第二个松散语法绑定,
只有@ConfigurationProperties支持
@Value他也有他的好处,他还支持SPEL,Spring的表达式语言,SPEL支持方面,@ConfigurationProperties他就不支持了,
而我们的@Value它是支持的,我们在@Value上写一个东西,我们之前看过,他能帮我们算出来,
person.age=#{11*2}
我们发现就错了,错的原因他说,这是age,你要注入这个值的时候,typeMisMatch,类型转换异常,所以这一块他不支持Spring
表达式,这是我们的第二个区别
第三个区别呢,@ConfigurationProperties支持JSR303校验,我们给他里面再扩展一个,
JSR303数据校验,数据校验@ConfigurationProperties,他能支持,我们@Value他就不支持,
我们给配置文件注入值的时候,我们还可以校验一下,我们可以这样,用@Validated,我们这个JAVABEAN
里面的属性,要校验,比如我们加上第一个校验,我来给一个校验规则,比如@Email,就是lastName你要填成邮箱格式,
lastName必须是邮箱格式,我们是@ConfigurationProperties的情况下,我来运行,这一块就报错了,在注入lastName的时候,
错误代码email的,他还有错误的提示消息,不是一个合法的电子邮件地址,说明他启动了校验,但是如果我们换成@Value,
让他来给我们注入值,来看一下这个校验还能不能生效呢,发现这个校验是无效的,发现照样是取到值了,这是他们的这个区别,
JSR303是@ConfigurationProperties支持,@Value不支持,我们无论是配置文件,你写什么都行,不管是yml,还是properties,
他们都能获取到值,只是每一个获取值的区别,包括JSR303数据校验的时候,记录一下数据校验,配置文件注入值数据校验,
数据校验必须使用@ConfigurationProperties才可以
到底我们使用哪个比较合适呢,我们再来看一个最大的不同,我们来到@ConfigurationProperties,我们把它注掉,
他获取值一切都是正常的,而且还能做校验,校验我也注释掉,我不要校验功能了,现在这些值我不以他们为例,我用
@Value来获取Map的值,
@Value("${person.maps}")
我们看他能不能获取到,现在用的是@Value注解,我们启动的时候发现报错了,就是解析这个map,最大的在这,我们这个
@Value注解,在复杂类型封装,我们这个@ConfigurationProperties,它是能支持的,而我们的@Value它是不能,他只能取出
一些基本类型的数据,我们什么时候用@ConfigurationProperties,什么时候用@Value,如果说我们只是在某个业务逻辑中
需要获取一下配置文件中的某项值,那就使用@Value,那举一个例子
除了用@ConfigurationProperties,从person里面读取所有的属性,我们还有一种方式,我们有一个注解是@Value,
这是我们Spring的一个底层注解,以前我们都是用配置的方式
<bean class="person">
我写一个Controller,就叫HelloController,我用@RestController标注上来,他就一个方法,这个hello给谁说呢,
我想Hello加上一个人名字,这个人名在配置文件中,我可以给他里面写一个name,而这个name从配置文件中@Value,
来获取就行了,
@Value("${person.last-name}")
private String name;
然后就给这个人打招呼,我们来访问一些这个请求,我们来访问这个sayHello请求
http://localhost:8080/sayHello
package com.learn.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Value("${person.last-name}")
private String name;
@ResponseBody
@RequestMapping("/sayHello")
public String sayHello() {
return "Hello" + name;
}
}
package com.learn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Sprint Boot应用
* @author Leon.Sun
*
*/
@SpringBootApplication
public class SpringBoot02ConfigApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(SpringBoot02ConfigApplication.class,args);
}
}
我们只是从配置文件中获取一下这个值,就使用@Value,如果说我们专门写了一个JAVABEAN来和配置文件来进行映射,
这就类似于我们和数据库里的记录,我们专门来写一个POJO一样,一个javaBean来映射配置文件中的值,我们就直接
使用@ConfigurationProperties,他就一次性把配置文件中相关的属性,都注入进来了,那就使用他,这是他们的区别,
当然在合适的时候,你如果需要用到其他的注解,那你就两个结合来用,他们的区别