Spring Boot 的配置文件和自动配置原理
使用 Spring Initializr 快速创建 Spring Boot 项目
IDEA:使用 Spring Initializr 快速创建项目
继承关系-springboot 的 maven 项目
- 使用 spring initializr 新建一个父 maven,type 选择 POM
- 在父 maven 项目中新建模块,使用 spring initializr 新建一个子 maven,type选择 maven project
修改子项目中的继承方式:
之前:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.6</version> <relativePath/> <!-- lookup parent from repository --> </parent>
修改后:
<parent> <groupId>com.SpringBoot</groupId> <artifactId>springboot_parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent>
spring_initializr 继承 springboot_parent 继承 spring-boot-starter-parent
默认生成的 Spring Boot 项目:
resource文件夹中的目录结构
- static:保存所有的静态资源,js css images;
- template:保存所有的模板页面;(Spring Boot 默认 jar 包使用嵌入式的 Tomcat,默认不支持 JSP 页面);可以使用模板引擎(freemarker、thymeleaf)
- application.properties:Spring Boot 应用的配置文件;可以修改一下默认设置;
自定义 SpringApplication
其他的上官网看。
lazy-initialization:懒加载
# 懒加载设置,要在使用 bean 的时候才会去创建 bean 实例,否则不创建 spring.main.lazy-initialization=true
配置文件的使用
SpringBoot 使用一个全局的配置文件或者叫核心配置文件,配置文件名在约定的情况下 名字是固定的;
配置文件的作用:修改 SpringBoot 自动配置的默认值;SpringBoot 在底层都给我们自动配置好;
两种配置文件的格式:
application.properties 的用法:扁平的 k/v 格式。
server.port=8081 server.servlet.context-path=/wyu
application.yml 的用法:树型结构。
server: port: 8081 servlet: context-path: /wyu
建议使用 yml,因为它的可读性更强。
YAML语法:
k:(空格)v:表示一对键值对(空格必须有);
以空格的缩进来空值层级关系;只要是左对齐的一列数据,都是同一个层级的;
属性和值也是大小写敏感;
配置文件加载顺序:
- application.yml
- application.yaml
- application.properties
外部约定配置文件加载顺序:
springboot 启动还会扫描以下位置的 application.properties 或者 application.yml 文件作为 Spring Boot 的默认配置文件
下面无序列表优先级从低到高
classpath 根目录下的
classpath 根 config/
项目根目录
如果当前项目是继承/耦合关系 maven 项目的话,项目根目录为父 maven 项目的根目录。
项目根目录 /config
直接子目录 /config
配置文件值注入
可以使用
@Value
标签一个一个属性绑定,也可以使用@ConfigurationProperties
标签根据 yml 或者 properties 文件一次性绑定松散绑定
user: user-name: 啊章 user: userName: 啊章 user: user_name: 啊章 user: USERNAME: 啊章
以上四种命名是可以自动绑定 bean 属性 User.username
- 如果输出中文乱码,则需要调一下setting:
@Value
和@ConfigurationProperties
的获取值比较:
@ConfigurationProperties
@Value 功能 批量注入配置文件中的属性 一个个指定 松散绑定 支持 支持,有限 SpEL 不支持 支持 JSR303数据校验 支持 不支持 复杂类型封装 支持 不支持 自动提示 支持 不支持 - 导入配置文件处理器并且勾选如图设置,以后编写配置就有提示了:
<!-- 会生成 META-INF 元数据 用于提供 idea 自动提示配置文件的 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <!-- option: 如果依赖不会传播 就是说别的项目依赖本项目,那么本项目的这个依赖不会被别的项目依赖 --> <optional>true</optional> </dependency>
配置文件赋值:
对象、Map(属性和值)(键值对):
对象是 k : v 的方式
girl-friend: 18 : IU 20 : 庄达菲
行内写法:
girl-friend: {18: IU,20: 庄达菲}
数组(List、Set):
用 - 值 表示数组中的一个元素
hobbies: - 唱 - 跳 - rap - 篮球
行内写法
hobbies: [唱,跳,rap,篮球]
JSR303数据校验
<!-- 数据校验 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
@NotNull
要使用 javax.validation 包下面的验证注解
配置文件占位符
随机数
#随机值 ${random.value} #随机 int 值 ${random.int} #随机值 ${random.long} #随机值 ${random.uuid} # 10 以内的随机 int 值 ${random.int(10)} #范围为 1024 到 65536 的随机 int 值 ${random.}int[1024,65536]}
占位符获取之前配置的值,如果没有可以使用:指定默认值
Profile文件的加载
对于应用程序来说,不同的环境需要不同的配置。
多 Profile 文件
- Spring 官方给出的语法规则是 application-{profile}.properties(.yaml/.yml)
如果需要创建自定义的 properties 文件时,可以用 application-xxx.properties 的命名方式。
开发环境下:
生产环境下:
若我们需要在两种环境下进行切换,只需要在 application.properties 中加入如下内容即可。
spring.profiles.active=prod
激活指定 profile
- 在配置文件中指定 spring.profiles.active=dev
命令行:
java -jar configuration_file-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
还可以通过 spring.config.location 来改变默认的配置文件
使用 spring.config.location 指定的配置文件,是不会进行互补。
java -jar configuration_file-0.0.1-SNAPSHOT.jar --spring.profiles.location=D:/application.properties
还可以通过 spring.config.name 来改变默认的配置文件
java -jar configuration_file-0.0.1-SNAPSHOT.jar --spring.profiles.name=application-prod;
所有配置文件按以下顺序考虑:优先级从低到高
- 打包在 jar 中配置文件
- 打包在 jar 中 profile
- 打包在 jar 之外的配置文件
- 打包在 jar 之外的 profile
通配符位置
如果具有某些 Redis 配置和某些 mysql 配置,则可能需要将这两个配置分开,同时要求这两个配置都存在于 application.properties 文件中。这可能会导致两个不同的 application.properties 文件安装在诸如不同的位置 /config/redis/application.properties 和 /config/mysql/application.properties。在这种情况下,通配符位置为 config/*/,将导致两个文件都被处理。
配置文件读取方式:优先级从低到高
@PropertySource@Configuration 类上的注解。请注意,Environment 在刷新应用程序上下文之前,不会将此类属性源添加到中。现在配置某些属性(如 logging. 和 spring.main. 在刷新开始之前先读取)为时已晚。
- 会和约定的配置文件形成互补
- 一定要指定 .properties 配置
@SpringBootApplication @PropertySource("classpath:appSource.properties") public class Application { public static void main(String[] args) throws IOException {}
- 默认属性(通过设置指定 SpringApplication.setDefaultProperties)
- 会和约定的配置文件形成互补
```java
@SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
SpringApplication springApplication = new SpringApplication(Application.class);
// 创建 properties
Properties properties = new Properties();
// 通过当前类的 ClassLoader
InputStream is = Application.class.getClassLoader().getResourceAsStream("app.properties");
// 将输入流读取成 properties 对象
properties.load(is);
springApplication.setDefaultProperties(properties);
springApplication.run(args);
}
}
```
- 配置数据(例如 application.properties 文件)
- 约定配置文件
- 操作系统环境变量。
- 会使约定配置文件失效
- idea

- windows

- Java 系统属性(System.getProperties())。
- 会使约定配置文件失效
- idea

- 命令行 java 属性

- JNDI 属性 java:comp/env。
- ServletContext 初始化参数。

- ServletConfig 初始化参数。

- 来自的属性 SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的嵌入式 JSON)。
- 命令行参数。
- 会使约定配置文件失效
```cmd
java -jar configuration_file-0.0.1-SNAPSHOT.jar --spring.profiles.location=D:/application.properties
```
- properties 测试中的属性。可用于测试应用程序的特定部分 @SpringBootTest 的测试注释和注释。
- @TestPropertySource 测试中的注释。
- 用在单元测试上的

- $HOME/.config/spring-boot 当 devtools 处于活动状态时,目录中的 Devtools全局设置属性。
- 配置文件加载位置
Spring Boot 的配置和自动配置原理
@SpringBootApplication:Spring Boot 应用标注在某个类上说明这个类是 SpringBoot 的主配置类,SpringBoot 需要运行这个类的 main 方法来启动 SpringBoot 应用;
@Target(ElementType.TYPE) //设置当前注解可以标记在哪 @Retention(RetentionPolicy.RUNTIME) //当注解标注的类编译以什么方式保留 RetentionPolicy.RUNTIME 会被 jvm 加载 | 反射的方式:class.getAnnotionbytype(Autowreid.class) @Documented //java doc 会生成注解信息 @Inherited //是否会被继承 @SpringBootConfiguration //Spring Boot 的配置类;标注在某个类上,表示这是一个 Spring Boot 的配置类; @Configuration //配置类上来标注这个注解;配置类——配置文件;配置类也是同期中的一个组件;@Component @EnableAutoConfiguration //开启自动配置功能;以前我们需要配置的东西,Spring Boot 帮我们自动配置;@EnableAutoConfiguration 告诉 SpringBoot 开启自动配置功能;这样自动配置才能生效; @ComponentScan //扫描包 相当于在 spring.xml 配置中 <context:component-scan> 但是没有指定 basepackage,如果没有指定,spring 底层会自动扫描当前配置类所有在的包 TypeExcludeFilter:springboot //对外提供的扩展类,可以供我们去按照我们的方式进行排除 AutoConfigurationExcludeFilter //排除所有配置类并且是自动配置类中里面的其中一个 @AutoConfigurationPackage //将当前配置类所在包保存在 BasePackages 的 Bean 中。供 spring 内部使用
以 HttpEncodingAutoConfiguration (Http 编码自动配置)为例解释自动配置原理;
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { private final Encoding properties; public HttpEncodingAutoConfiguration(ServerProperties properties) { this.properties = properties.getServlet().getEncoding(); } @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE)); return filter; }
@Configuration(proxyBeanMethods = false)
标记了 @Configuration,Spring 底层会给配置创建 cglib 动态代理。
作用:防止每次调用本类的 Bean 方法而重新创建对象,Bean 是默认单例的。
@EnableConfigurationProperties(ServerProperties.class)
启用可以再配置类设置的属性 对应的类
- @xxxConditional 根据当前不同的条件判断,决定这个配置类是否生效?
@Conditional 派生注解(Spring 注解版原生的 @Conditional 作用)
作用:必须是 @Conditional 指定的条件成立,才给容器中添加组件,配置配里面的所有内容才能生效;
@Conditional 扩展注解作用 (判断是否满足当前指定条件) @ConditionalOnJava 系统的 java 版本是否符合要求 @ConditionalOnBean 容器中存在指定的 Bean; @ConditionalOnMissingBean 容器中不存在指定的 Bean; @ConditionalOnExpression 满足 SpEL 表达式指定 @ConditionalOnClass 系统中有指定的类 @ConditionalOnOnMissingClass 系统中没有指定的类 @ConditionalOnSingleCandidate 容器中只有一个指定的 Bean,或者这个 Bean 是首选 Bean @ConditionalOnProperty 系统中指定的属性是否有指定的值 @ConditionalOnResource 类路径下是否存在指定资源文件 @ConditionalOnWebApplication 当前是 Web 环境 @ConditionalOnNotWebApplication 当前不是 Web 环境 @ConditionalOnJndi JNDI 存在指定项 可以通过设置配置文件中:启用 debug=true 属性来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效
============================ CONDITIONS EVALUATION REPORT ============================ Positive matches: **表示自动配置类启用的** ----------------- ...... Negative matches: **没有匹配成功的自动配置类** ----------------- ......