目录:
- Spring Boot的核心配置与注解 :
- 1. 全局配置文件 ( application.properties / application.yaml:创建项目时候自动生成,其会被“自动导入”到“程序”中 )
- application.properties配置文件
- application.yaml 配置文件 (推荐使用)
- 当value值为 “普通数据类型” (如 : 数字、字符串、布尔等)
- 当value值为 “数组” 或 “单列集合”
- 当value值为 “Map集合” 或 “对象类型”
- application.yaml 配置文件的“应用案例”
- 2. “配置文件属性值” 的 “注入”
- 使用@ConfigurationProperties( )注解将“配置文件”中的“属性值”注入到“属性”中 (注入“个别属性值”)
- 使用@Value( )注解将“配置文件”中的“属性值”注入到“属性”中 (注入“个别属性值”)
- 两种注解“对比分析”
- 底层框架
- 功能
- 属性 setter 方法
- 复杂类型属性注入
- 松散绑定
- JSR303 数据校验
- SpEL表达式 ( 使用“SpEL表达式”为属性“直接注入值” )
- 如何选择使用这“两种注解”?
Spring Boot的核心配置与注解 :
作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!
该文章参考学习教材为:
《Spring Boot企业级开发教程》 黑马程序员 / 编著
文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!(侵权可联系我,进行删除,如果雷同,纯属巧合)
1. 全局配置文件 ( application.properties / application.yaml:创建项目时候自动生成,其会被“自动导入”到“程序”中 )
- 全局配置文件 ( applicationContext.properties )能够对一些 默认配置值进行修改。Spring Boot 使用一个 ① application.properties 或者 ② application.yaml 的文件作为 全局配置文件,该文件存放 在 src/main/resource目录 或者 类路径的 /config,一般会选择 resource目录。
application.properties配置文件
使用 Spring Initializr方式构建Spring Boot项目时,会在 src/main/resources目录 下 自动生成一个空 application.properties文件 ,Spring Boot项目启动时会自动加载application.properties文件。
我们可以在application.properties 文件中定义 Spring Boot 项目的相关属性,当然,这些相关属性可以是 系统属性、环境变量 、命令参数等信息,也可以是 自定义配置文件名称 和 位置。示例代码如下:
spring.application.name=chapter_02 server.address=80 server.port=8443 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.config.additional-location= spring.config.location= spring.config.name=application
关于applicationContext.properties 的 案例 ( 例子如 ) :
Pet.java :
package com.myh.chapter_03.domain; public class Pet { private String type; private String name; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "type='" + type + '\'' + ", name='" + name + '\'' + '}'; } }
Person.java:
package com.myh.chapter_03.domain; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; import java.util.Map; @Component //用于将Person类加入到IOC容器中 (只有这样Person对象才能被 @ConfigurationProperties()注解赋值 ) @ConfigurationProperties(prefix = "person")//将配置文件(application.properties)中以person开头的数据通过“set方法”注入到该类中"属性" public class Person { /** * 通过 @ConfigurationProperties(prefix = "person") 注解来将 application.properties中的"数据"注入到 * 下面的“属性”中 */ private int id; private String name; private List hobby; private String[] family; private Map map; private Pet pet; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getHobby() { return hobby; } public void setHobby(List hobby) { this.hobby = hobby; } public String[] getFamily() { return family; } public void setFamily(String[] family) { this.family = family; } public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", hobby=" + hobby + ", family=" + Arrays.toString(family) + ", map=" + map + ", pet=" + pet + '}'; } }
@ConfigurationProperties(prefix =“person”)注解 的 作用 是将配置文件中以person开头的属性值通过setter方法注入实体类对应属性 中。@Component注解 的作用是将当前注入属性值的 Person类对象作为 Bean 组件放到 Spring 容器中,只有 这样它才能被 @ConfigurationProperties注解赋值。
在上述自定义 Person类中,添加了一个 @Component注解,将该自定义类作为 Spring容器的组件 ( 简而言之,就是 将该类交给IOC容器管理 ),其根本目的是让 Spring Boot 可以自动扫描到该组件,然后进行其他功能实现。
application.properties:
#对实体类对象Person进行属性配置 person.id = 1 person.name = tom person.hobby = play,read,sleep person.family = father,mother person.map.k1 = v1 person.map.k2 = v2 person.pet.type = dog person.pet.name = kity
Spring Boot默认全局配置文件 : application.properties 中的数值将会通过 @ConfigurationProperties( ) 注解 注入到对应 的 实体类 中。
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.myh</groupId> <artifactId>chapter_03</artifactId> <version>0.0.1-SNAPSHOT</version> <name>chapter_03</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- web应用场景依赖启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 单元测试依赖启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>test</scope> </dependency> <!-- “热部署”依赖启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- 是生成配置元数据,以提供更好的配置文件支持和开发体验。它能够帮助开发人员更方便地使用配置文件,并提高开发效率 --> <!-- 在编写application.properties配置文件时,由于要配置的Person 对象属性是我们自定义的,SpringBoot 无法自动识别,所以不会有任何书写提示。在实际开发中,为了出现代码提示的效果来方便配置,在使用@ConfigurationProperties注解进行配置文件属性值注入时,可以在pom.xmI文件中添加一个Spring Boot 提供的配置处理器依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency> </dependencies> <!-- Maven打包工具插件 --> <!-- <build>--> <!-- <plugins>--> <!-- <plugin>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-maven-plugin</artifactId>--> <!-- </plugin>--> <!-- </plugins>--> <!-- </build>--> </project>
Chapter03ApplicationTests.java ( 单元测试类 ):
package com.myh.chapter_03; import com.myh.chapter_03.domain.Person; import org.junit.jupiter.api.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; @RunWith(SpringRunner.class) //测试运行器,并加载SpringBoot测试注解 @SpringBootTest //标记该类为“单元测试类”,并加载项目的上下文环境ApplicationContext class Chapter03ApplicationTests { @Autowired private Person person; @Test void contextLoads() { System.out.println(person); } }
运行 contextLoads( )方法,控制台输出结果如下图所示 :
方法执行结果.jpg)信息成功打印,说明了 application.properties文件 属性配置正确,并通过 相关注解自动完成 了 “属性注入”。
application.yaml 配置文件 (推荐使用)
- YAML文件格式 是 Spring Boot 支持 的一种 JSON 超集文件格式,相较于传统的Properties配置文件,YAML文件以数据为核心,是一种更为 直观 且 容易被计算机识别 的 数据序列化格式。
- application.yaml 配置文件的 工作原理 和 application.properties 是一样的,只不过YAML格式配置文件看起来 更简洁一些。
- application.yaml 文件用“ key: + 空格 + value”格式配置属性,使用缩进控制层级关系。这里我们 针对不同数据类型 的 属性值,介绍一下YAML文件配置属性的 写法,具体如下所示 。
当value值为 “普通数据类型” (如 : 数字、字符串、布尔等)
(1) value 值为 普通数据类型( 如数字、字符串、布尔等)
当 YAML 配置文件中配置的 属性值 为 普通数据类型 时,可以 直接配置对应的属性值,同时对 字符串类型的属性值,不需要额外添加引号,示例代码如下 :#当属性值为普通数据类型(如:数字、字符串、布尔等),属性值不需要”额外添加引号“ #8081 和 /hello因为是"普通数据类型",所以都没添加额外的引号 #port和path属于“同一级别” Server: port: 8081 path: /hello
当value值为 “数组” 或 “单列集合”
(2) value 值为 数组 或 单列集合
当YAML 配置文件中配置的 属性值 为 数组 或 单列集合类型 时,主要有 两种书写方式 :①缩进式写法 和 ②行内式写法。①缩进式写法 :
#缩进式写法 person1: hobby: - play - read - sleep person2: hobby: play, read, sleep
②行内式写法 :
#行内式写法 person4: hobby: [play,read,sleep] #使用行内式设置属性值时, []是可以省略的,程序会自动匹配校队"属性的值" person5: hobby: play,read,sleep
当value值为 “Map集合” 或 “对象类型”
(3) value 值为 Map 集合 和 对象类型 时,主要同样 有两种书写方式 :①缩进式写法 和 ②行内式写法。
①缩进式写法 :
#value值为Map或对象时的写法 #Map类型 #缩进式写法 person6: map: k1: v1 k2: v2
②行内式写法 :
#Map类型 #行内式写法,此处用的符号是: 大括号{} person7: map: {k1: v1,k2: k3}
ps :
此处用的 符号 是: 大括号{ }
application.yaml 配置文件的“应用案例”
application.yaml :
#对实体类对象Person进行属性设置, 一样是通过 @ConfigurationProperties()注解来将下面的"数据值"注入到"类"的"属性"中的 person2: id: 1 name: 张三 hobby: [play,read,sleep] family: [father,mother] map: {k1: v1,k2: v2} pet: {type: dog,name: kitty}
Person.java :
package com.myh.chapter_03.domain; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; import java.util.Map; @Component //用于将Person类加入到IOC容器中 (只有这样Person对象才能被 @ConfigurationProperties()注解赋值 ) @ConfigurationProperties(prefix = "person2")//将配置文件( application.yaml )中以person2开头的数据通过“set方法”注入到该类中"属性" public class Person { /** * 通过 @ConfigurationProperties(prefix = "person") 注解来将 application.properties中的"数据"注入到 * 下面的“属性”中 */ private int id; private String name; private List hobby; private String[] family; private Map map; private Pet pet; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getHobby() { return hobby; } public void setHobby(List hobby) { this.hobby = hobby; } public String[] getFamily() { return family; } public void setFamily(String[] family) { this.family = family; } public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } public Pet getPet() { return pet; } public void setPet(Pet pet) { this.pet = pet; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", hobby=" + hobby + ", family=" + Arrays.toString(family) + ", map=" + map + ", pet=" + pet + '}'; } }
Chapter03ApplicationTests.java ( 单元测试类 ):
package com.myh.chapter_03; import com.myh.chapter_03.domain.Person; import org.junit.jupiter.api.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; @RunWith(SpringRunner.class) //测试运行器,并加载SpringBoot测试注解 @SpringBootTest //标记该类为“单元测试类”,并加载项目的上下文环境ApplicationContext class Chapter03ApplicationTests { @Autowired private Person person; @Test void contextLoads() { System.out.println(person); } }
运行 contextLoads( )方法,控制台输出结果如下图所示 :
信息成功打印,说明了 application.yaml文件 属性配置正确,并通过 相关注解自动完成了“属性注入”。通过对比可以发现,YAML配置文件的格式更加简洁、方便、推荐使用YAML格式文件。
2. “配置文件属性值” 的 “注入”
使用Spring Boo 全局配置文件 ( application.properties / application.yaml )配置 属性 时,① 如果配置的属性是Spring Boot 默认提供的属性 ,例如服务器端口server.port,那么Spring Boot内部会自动扫描并读取属性值 ( 因为那是 默认提供的属性 )。 ② 如果配置的属性是 用户自定义属性,例如 :自定义的 Person 实体类属性,则必须在程序中注入这些配置属性 ( 通过 @ConfigurationProperties( )注解 来 进行“属性值”的注入 )方可生效。
Spring Boot 支持 多种注入配置文件属性的方式 :
① 使用 注解@ConfigurationProperties ( )注解“注入属性” ② 使用 @Value( )注解 “注入属性”
使用@ConfigurationProperties( )注解将“配置文件”中的“属性值”注入到“属性”中 (注入“个别属性值”)
Spring Boot提供的 @ConfigurationProperties注解 用来快速、方便地 将配置文件中的 自定义
属性值批量注入 某个Bean 对象的 多个对应属性 中。假设现在有一个配置文件,使用 @ConfigurationProperties 注入配置文件的属性,示例代码如下 :@Component //将该类交给IOC容器管理,变成一个bean //该注解的作用: 将配置文件中自定义的"属性值"注入到某个bean对象中的"对应属性"中 @ConfigurationProperties(prefix = "person")//将配置文件( application.properties/application.yaml )中以后person开头的数据通过“set方法”注入到该类中"属性" public class Person { private int id; //属性的set方法 public void setId(int id) { this.id = id; } }
上述代码使用 @Component 和 @ConfigurationProperties(prefix =“person”) 将 配置文件中 的 每个属性映射 到 person类属性中 。
需要注意 的是,使用 @ConfigurationProperties 注解 批量注入属性值 时,要保证配置文件中的 属性 与对应实体类的 属性名一致 ,否则无法 正确 获取并注入属性值 。
使用@Value( )注解将“配置文件”中的“属性值”注入到“属性”中 (注入“个别属性值”)
@Value注解 是 Spring框架提 供的,用来 读取配置文件中的属性值 并逐个 注入Bean对象 的 对应属性中。Spring Boot 框架对Spring 框架中的 @Value注解进行了 默认继承,所以在Spring Boot 框架中还可以使用该注解 读取和注入配置文件属性值。
@Component //将该类交给IOC容器管理,变成一个bean public class Person { @Value("${person.id}") //将配置文件中的“属性值”注入到该类的属性中 private int id; }
上述代码中,@Component注解和 @Value注解用于 注入Person的id属性。其中,@Value 不仅支持注入Person的 id 属性,而且 还可以直接为id属性赋值,这是 @ConfigurationProperties( )注解 不支持 的。
例子如 :
Student.java :
package com.myh.chapter_03.domain; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; import java.util.Map; @Component //将该类添加到IOC容器中,作为一个bean(被IOC容器管理) public class Student { //用该注解将配置文件中的"属性值"注入到该类的“属性”中 @Value("${person.id}") private int id; @Value("${person.name}") private String name; private List hobby; private String[] family; private Map map; private Pet pet; @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", hobby=" + hobby + ", family=" + Arrays.toString(family) + ", map=" + map + ", pet=" + pet + '}'; } }
pom.xml :
#对实体类对象Person进行属性设置, 一样是通过 @ConfigurationProperties()注解来将下面的"数据值"注入到"类"的"属性"中的 person: id: 1 name: tom hobby: [play,read,sleep] family: [father,mother] map: {k1: v1,k2: v2} pet: {type: dog,name: kitty}
Chapter03ApplicationTests.java (测试类):
package com.myh.chapter_03; import com.myh.chapter_03.domain.Person; import com.myh.chapter_03.domain.Student; import org.junit.jupiter.api.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; @RunWith(SpringRunner.class) //测试运行器,并加载SpringBoot测试注解 @SpringBootTest //标记该类为“单元测试类”,并加载项目的上下文环境ApplicationContext class Chapter03ApplicationTests { @Autowired private Student student; @Test public void studentTest() { System.out.println(student); } }
运行 studentTest( )方法,控制台输出结果如下图所示 :
注意点 :
使用 @Value( )注解 注入的 属性类型 只能是“ 基本数据类型”。
两种注解“对比分析”
@ConfigurationProperties( )注解 和 @Value( )注解 的对比 如下表所示 :
对比 @ConfigurationProperties( )注解 @Value( )注解 底层框架 SpringBoot Spring 功能 批量注入配置文件中的属性 单个注入 setter 方法 需要 不需要 复杂类型属性注入 支持 支持 松散绑定 支持 不支持 JSR303 数据校验 支持 不支持 SpEL表达式 不支持 支持
底层框架
@ConfigurationProperties注解是 Spring Boot框架自带 的;而 @Value 注解是 Spring 框架支持的,
只不过Spring Boot框架对Spring 进行了 默认支持,所以也可以使用@Value 注解的相关功能。
功能
@ConfigurationProperties能够将配置文件中的属性 批量注入 Bean对象,而@Value 只能 一个一个单独注入。
属性 setter 方法
- 在使用 @ConfigurationProperties注解进行配置文件 属性值读取注入 时,还必须为 每一个属性 设置 setter方法,通过对应的注解才能够将配置文件中的属性一一匹配并注入对应的 Bean 属性上。如果配置文件中没有配置属性值,则会自动将对应的 Bean 属性设置为空。
(用 @ConfigurationProperties注解必须为每一个属性设setter方法,这样才能完成属性值的注入)- @Value 完全不需要为属性设置setter方法,该注解会先通过表达式读取配置文件中指定的属性值,然后自动注入下方的Bean属性上。如果读取的配置文件属性为空,进行属性注入时程序会自动报错。
复杂类型属性注入
@ConfigurationProperties( )注解 和 @Value注解 支持 任意数据类型 的属性注入,包括基本数据类型和复杂数据类型。
松散绑定
@ConfigurationProperties注解进行配置文件属性值注入时,支持松散绑定语法。例如Person类有一个字符串类型的属性firstName,那么在配置文件中进行属性配置时可以使用如下配置方式,示例代码如下 :
person.firstName = james //标准写法,对应Person类属性名 person.first-name = james //使用横线“-”分隔多个单词 person.first_name = james //使用下划线"_"分隔多个单词 person.FIRST_NAME = james //使用大小写格式,推荐常量属性配置
如果要 注入上述松散绑定语法的属性,那么使用 @Value 注入是无效的,只能使用@ConfigurationProperties。
JSR303 数据校验
@ConfigurationProperties注解进行配置文件属性值注入时,支持JSR303数据校验 ,其主要作用是 校验配置文件 中 注入对应Bean属性 的值是否符合相关值的规则,示例代码如下 :
@Component //加入到IOC容器中 @ConfigurationProperties(prefix = "person") @Validated //引入Spring框架支持的"数据校验规则" public class Example { @Email //对属性进行规则匹配 private String email; public void setEmail(String email) { this.email = email; } }
上述代码中,使用 @ConfigurationProperties注解注入配置文件属性值时,在实体类Example上引入 @Validated 注解进行数据校验,在属性email 上引入@Email 注解进行邮件规则校验。如果注入的配置文件属性值不符合相关校验规则,程序会自动报错。@Value 注解不支持 JSR303数据校验功能。
SpEL表达式 ( 使用“SpEL表达式”为属性“直接注入值” )
@Value 注解 注入配置文件属性时,支持 SpEL表达式语法,即“#{xx}”。例如 Person 类有一个整数类型的属性id,直接使用 SpEL 表达式语法进行属性注入 ( 使用SpEL表达式直接为属性注入值 )
示例代码如下 ://用SpEL来定义一个值, #{5*2} 是一个简单的数学表达式,它计算 5乘以 2的结果,将给结果注入到id属性中 @Value("#{5*2}") private int id;
上述代码在 不使用配置文件 的情况下,直接使用 @Value注解 支持的 SpEL表达式注入Bean ( 通过该 注解支持的SpEL表达式来“直接”为“属性注入值” )。而 @ConfigurationProperties注解 不支持此功能。
如何选择使用这“两种注解”?
- 如果只是针对某一个业务需求,要引入配置文件中的个别属性值,推荐使用 @Value( )注解。
( 如果只要 注入一两个属性值,用 @Value( )注解 )- 如果针对某个JavaBean类,需要 批量注入属性值,则推荐使用@ConfigurationProperties( )注解
注解。
(如果要 注入多个属性值,推荐使用 @ConfigurationProperties( )注解)