1. Spring Boot的默认配置
Spring Boot使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让你的项目快速运行起来。所以,我们要想把Spring Boot玩的溜,就要懂得如何开启各个功能模块的默认配置,这就需要了解Spring Boot的配置文件application.properties。 Spring Boot默认配置文件为CLASSPATH(resources目录)下的application.properties(yml)。
Spring Boot使用了一个全局的配置文件application.properties,可以放在src/main/resources(yml)目录下或者类路径的/config下,总之打包后需要在CLASSPATH下。
Sping Boot的全局配置文件的作用是对一些默认配置的配置值进行修改。
注:如果你工程没有这个application.properties(yml),那就在src/main/java/resources目录下新建一个File,命名为application.properties(yml)。
1.1 配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
配置文件的作用 : 修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;
- YAML(YAML Ain’t Markup Language);
- YAML A Markup Language:是一个标记语言;
- YAML isn’t Markup Language:不是一个标记语言;
标记语言:
以前的配置文件; 大多都使用的是 xxxx.xml文件;YAML : 以数据为中心,比json、xml等更适合做配置文件;
YAML:配置例子
1 | server: |
相当于XML:
1 | <server> |
1.2 YAML语法
1.2.1 基本语法
K:(空格)V:表示一对键值对(空格必须有);以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
1 | server: |
属性和值也是大小写敏感;
1.2.2 值的写法
- 字面量: 普通的值(数字,字符串,布尔)
1
2
3
4
5
6
7
8
9
10
11K: V:字面直接来写;
字符串默认不用加上单引号或者双引号;
" ":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi":输出:zhangsan \n lisi
' ':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: 'zhangsan \n lisi';输出:zhangsan 换行 lisi - 对象、Map(属性和值)(键值对)
- K: V:在下一行来写对象的属性和值的关系;注意缩进
对象还是K: V的方式
1 | user: |
行内写法:
1 | user: {id: 1,username: 张三,age: 21} |
- 数组(List、Set)
用-值表示数组中的一个元素行内写法1
2
3
4pets:
- cat
- dog
- pig1
pets: [cat,dog,pig]
2. 配置文件值注入
application.properties(yml)提供自定义属性的支持,这样我们就可以把一些常量配置在这里:yml:语法中间有空格
1 | name: "张三" |
然后直接在要使用的地方通过注解@Value(value=”${name}”),使用SPEL表达式取数据,值就可以绑定到你想要的属性上面
1 | @RestController |
我们启动工程输入http://localhost:8080 就可以看到打印了”张三====21”。
有时候属性太多了,一个个绑定到属性字段上太累,官方提倡绑定一个对象的bean,这里我们建一个User.java类,顶部需要使用注解@ConfigurationProperties(prefix = "user")来指明使用哪个,注: 必须和属性名对应,否则为null
1 | user: |
使用 @ConfigurationProperties 注解在idea会给我们提示,需要导入配置文件处理器。
在pom导入配置文件处理器,以后编写配置就有提示了:
1 | <!--导入配置文件处理器,配置文件进行绑定就会有提示--> |
3. @Value获取值和@ConfigurationProperties获取值比较
@Value是以前spring底层的,使用@Value需要一个一个参数指定,@ConfigurationProperties批量注入配置文件中的属性。更多比较如下:
|—|@ConfigurationProperties | @Value|
|—|—|
|功能 | 批量注入配置文件中的属性 | 一个个指定|
|松散绑定(松散语法)| 支持 | 不支持|
|SpEL | 不支持 | 支持|
|JSR303数据校验 | 支持 | 不支持|
|复杂类型封装 | 支持 | 不支持|
总结: 配置文件yml还是properties他们都能获取到值;如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
4. 配置文件注入值数据校验
类上添加@Validated注解,实现JSR303校验
@ConfigurationProperties支持JSR303数据校验,@Value不支持JSR303数据校验。
1 | @Component //必须把类加到Spring容器中被管理 |
5. @PropertySource&@ImportResource&@Bean
@PropertySource:加载指定的配置文件;
person.properties
1 | person.last-name=hfbin |
Person.java
1 | @PropertySource(value = {"classpath:person.properties"}) |
@ImportResource: 导入Spring的配置文件,让配置文件里面的内容生效;Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上
1 | @SpringBootApplication |
SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式
- 配置类 @Configuration ——>Spring配置文件
- 使用 @Bean 给容器中添加组件
1 | /** |
5.1 获取Spring容器
SpringBoot平台下采用ApplicationContextAware的方式完成ApplicationContext实例的获取,并通过ApplicationContext实例完成对Spring管理的Bean实例手动获取。
1 | @Component |
6. 配置文件占位符
6.1 随机数
1 | ${random.value}、${random.int}、${random.long} |
6.2 占位符获取之前配置的值,如果没有可以是用:指定默认值
可以在配置文件中引用前面配置过的属性(优先级前面配置过的这里都能用)。
1 | person.last-name=张三${random.uuid} |
7. Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、 指定参数等方式快速切换环境 。
7.1 多Profile文件
我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml
比如开发环境:application-dev.properties
生产环境 :application-prod.properties
默认使用application.properties的配置
7.2 yml支持多文档块方式
1 | server: |
7.3 激活指定profile
在配置文件
application.properties中指定spring.profiles.active=dev命令行: 可以直接在测试的时候,配置传入命令:
1
java -jar spring-boot-panyucable-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
虚拟机参数
1
-Dspring.profiles.active=dev
7.4 配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
1 | –file:./config/ |
- 优先级由高到底,高优先级的配置会覆盖低优先级的配置;
- SpringBoot会从这四个位置全部加载主配置文件;互补配置;
- 我们还可以通过spring.config.location来改变默认的配置文件位置,项目打包好以后,
我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;这个对运维方面起到很大作用1
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
8. 自动配置原理
配置文件到底能写什么?怎么写?自动配置原;
8.1 常用配置
1 | server.port=9090 # 服务端口号 |
8.2 自动配置原理
- 先看
@SpringBootApplication @SpringBootConfiguration:标记当前类为配置类@EnableAutoConfiguration:开启自动配置@ComponentScan:扫描主类所在的同级包以及下级包里的Bean- 关键是
@EnableAutoConfiguration1
2
3
4
5
6
7
8
9
10
11@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}@AutoConfigurationPackage: 将主配置类(@SpringBootConfiguration标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器中,所以说,默认情况下主配置类包及子包以外的组件,Spring 容器是扫描不到的。
而通过@Import(AutoConfigurationImportSelector.class)导入的配置功能;AutoConfigurationImportSelector中的方法selectImports()调用getAutoConfigurationEntry()在调用getCandidateConfigurations()到loadFactoryNames(),得到待配置的class的类名集合,这个集合就是所有需要进行自动配置的类,而是否自动配置的关键在于META-INF/spring.factories·文件中是否存在该配置信息
loadFactoryNames() 中关键的三步:
- 从当前项目的类路径中获取所有 META-INF/spring.factories 这个文件下的信息。
- 将上面获取到的信息封装成一个 Map 返回。
- 从返回的
Map中通过刚才传入的EnableAutoConfiguration.class参数,获取该 key 下的所有值。
总结 :自动配置调用链
1 | @SpringBootApplication--->@EnableAutoConfiguration--->@Import(AutoConfigurationImportSelector.class)--->selectImports()--->getAutoConfigurationEntry()--->getCandidateConfigurations()--->loadFactoryNames() |
打开,如下图可以看到所有需要配置的类全路径都在文件中,每行一个配置,多个类名逗号分隔,而\表示忽略换行
以SpringApplicationAdminJmxAutoConfiguration类来看其主要构成部分
1 | @Configuration |
都能看到各种各样的条件判断注解,满足条件时就加载这个Bean并实例化,此类的条件注解是:@ConditionalOnProperty
1 | @ConditionalOnBean:当容器里有指定Bean的条件下 |
这些注解都组合了@Conditional注解,只是使用了不同的条件组合最后为true时才会去实例化需要实例化的类,否则忽略
这种spring4.X带来的动态组合很容易后期配置,从而避免了硬编码,使配置信息更加灵活多变,同时也避免了不必要的意外异常报错。使用的人只要知道配置的条件即可也不用去阅读源码,方便快捷,这也是sprignboot快捷方式带来的好处
参考HttpEncodingAutoConfiguration配置信息如下
1 | @Configuration |






