三、@PropertySource和@ImportSource
- @ImportResource注解可以读取指定的外部配置文件
- @PropertySource注解可以加载指定的配置文件
与Spring Boot无关的配置文件放在非主配置文件中,例如person相关的配置可以放在新建的person.properties中,可以使用@PropertySource注解来加载这个单独的配置文件,该注解仍然需要和@ConfigurationProperties注解搭配使用。
@PropertySource注解的使用
Person实体类上使用@PropertySource注解指定配置文件,配置全都写在person.properties中
代码语言:javascript复制@ConfigurationProperties(prefix = "person")
@PropertySource(value = {"classpath:person.properties"})
@Component
@Data
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
}
person.properties配置文件
代码语言:javascript复制person.lastName=stark1
person.age=19
person.birth=1980/12/12
person.boss=true
person.maps.k1=v1
person.maps.k2=v2
person.list=a,b,c
person.dog.name=pipi
person.dog.age=2
value是一个数组,可以写多个配置文件,@ConfigurationProperties(prefix = "person")默认是指application.properties配置文件,如果需要加载其他配置文件需要@PropertySource注解指定。
执行测试
@ImportResource注解的使用
@ImportResource注解的作用是可以导入Spring的配置文件,让配置文件里面的配置生效
@ImportResource注解的属性
value是一个数组,说明可以一次导入多个配置文件。
创建一个service包,创建HelloService,在Spring配置文件spring.xml中配置
代码语言:javascript复制public class HelloService {
}
在resources目录下创建一个Spring的配置文件spring.xml,用bean标签配置一个Java Bean注册到Spring容器中
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.lilith.configuration.service.HelloService">
</bean>
</beans>
在主程序上使用@ImportResources注解,导入spring.xml配置文件
代码语言:javascript复制@SpringBootApplication
@ImportResource(locations = {"classpath:spring.xml"})
public class ConfigurationApplication {
// 中间内容不变
}
在test包下增加HelloServiceTest,从容器中获取HelloService对象。
代码语言:javascript复制@SpringBootTest
public class HelloServiceTest {
@Autowired
private HelloService helloService;
@Test
public void testBean(){
System.out.println(helloService);
}
}
执行测试
控制台成功输出HelloSerivce对象,说明@ImportResource成功导入了spring.xml配置文件。
相比这种通过配置文件方式注册Bean或者组件,Spring Boot 推荐的方式是通过配置类的方式给容器中注入组件,通过全注解的方式注入。
新建config包,增加CustConfig配置类,增加@Configuration表明当前类是一个配置类,替代spring.xml配置文件,@Bean注解作用在方法上,方法的返回值就是注入到容器中的组件,方法名就是组件在容器中的名称。
代码语言:javascript复制@Configuration //表明当前类是一个配置类,替代spring.xml配置文件
public class CustConfig {
// 代替bean标签,将方法返回值注入容器中,默认方法名就是导入容器中的组件的名字
// 也可以通过name属性指定组件的名称
@Bean(name = "helloService")
public HelloService helloService(){
System.out.println("@Bean注解将HelloService组件添加到容器中!");
return new HelloService();
}
}
再次执行HelloServiceTest
通过配置类的方式也可以将组件注入容器中
四、配置文件的占位符
配置文件中可以使用占位符,支持配置文件中的属性引用。
Person实体类上读取主配置文件application.properties
代码语言:javascript复制# 使用随机值
person.last-name=stark1${random.value}
person.age=${random.int}
person.birth=1980/12/12
person.boss=true
person.maps.k1=v1
person.maps.k2=v2
person.list=a,b,c
# 引用前面配置过的属性
person.dog.name=${person.last-name}_pipi
person.dog.age=2
执行PersonTest测试
引用不存在的属性
当引用不存在的属性时会原样输出,修改配置文件,引用不存在的person.hello属性
代码语言:javascript复制person.dog.name=${person.hello}_pipi
执行PersonTest测试
{person.hello}原样输出。
为引用的不存在的属性设置默认值
属性不存在时为了避免原样输出也可以可以设置默认值,不存在的时候取默认值,在“:”后面设置默认值
代码语言:javascript复制person.dog.name=${person.hello:stark}_pipi
再次执行PersonTest测试
成功获取到设置的默认值
五、Profiles多环境支持
Profiles是Spring对不同环境提供不同配置功能的支持,可以通过激活或者指定参数的形式快速切换环境。
application.properties格式的多profiles文件方式
代码语言:javascript复制# 使用dev环境
spring.profiles.active=dev
application.yml格式多文档块方式
代码语言:javascript复制spring:
profiles:
# 激活test环境
active: test
命令行方式
代码语言:javascript复制java -jar xxx.jar --spring.prifles.active=dev
jvm参数方式
代码语言:javascript复制-Dspring.profiles.active=dev
properties格式配置文件多profiles方式
新建两个properties格式的配置文件,application-test.properties和application-dev.properties,通过设置端口号来确定使用的配置文件,默认使用application.properties
代码语言:javascript复制server.port=8081
server.servlet.context-path=/dev
代码语言:javascript复制server.port=8082
server.servlet.context-path=/test
可以在application.properties中增加配置激活哪个配置文件
代码语言:javascript复制spring.profiles.active=dev
启动应用
根据输出的端口号可以确定application-dev.properties配置文件被激活。
yml格式配置文件多文档块方式
YML配置文件中可以使用“---”来区分文档块,文档块就相当于一个单独的配置文件。使用文档块,可以将dev配置和test配置写在一个配置文件中
代码语言:javascript复制spring:
profiles:
# 激活dev配置
active: dev
---
# dev配置详情
server:
port: 8083
spring:
profiles: dev
---
# test配置详情
server:
port: 8084
spring:
profiles: test
---
将properties格式配置文件中的内容全部注释掉,启动应用
根据控制台输出的端口号可以确定,YML文档块中的DEV部分被激活
命令行参数方式
在执行启动命令时使用"--spring.profile.active=dev"选择激活的配置文件,命令行模式的优先级大于配置文件
启动应用
根据端口可以确定test配置被激活
也可以通过在终端中执行启动命令
代码语言:javascript复制java -jar spring-boot-configuration-0.0.1-SNAPSHOT.jar --spring.profiles.active=test
虚拟机参数方式
修改启动配置,在VM options中添加激活配置
再次启动
控制台成功输出指定的配置文件中设置的端口号
命令行、虚拟机配置和配置文件的优先级
命令行的优先级大于虚拟机
代码语言:javascript复制spring:
profiles:
active: dev
虚拟机优先级大于配置文件
代码语言:javascript复制spring:
profiles:
active: test
命令行 > 虚拟机 > 配置文件
六、配置文件位置的优先级
Spring Boot启动会扫描以下位置中的配置文件作为Spring Boot的默认主配置文件,优先级从高到低
- file:/config/
- file:/
- classpath:/config
- classpath:/ 也可以通过spring.config.location来改变默认配置,配置文件位置优先级也可以参考 你有没有掉进去过这些Spring Boot中的“陷阱“(上)- 配置文件加载顺序的“陷阱”
配置互补
工程目录下新增config目录,在该目录下新增application.yml,配置端口号
代码语言:javascript复制server:
port: 8085
resources目录下的配置文件新增内容
代码语言:javascript复制server:
servlet:
context-path: /app
port: 8080
启动项目,将VM参数和Programes参数清空
相同的配置被覆盖,不同的配置互补
spring.config.location 改变默认配置文件的位置
其他目录新建一个配置文件
代码语言:javascript复制server:
port: 8088
打包项目
代码语言:javascript复制java -jar spring-boot-configuration-0.0.1-SNAPSHOT.jar --spring.config.location=/Users/jingnan/Practice/March/application.yml
plus:spring.config.location不能实现配置互补,或直接取代所有配置文件
spring.config.additional-location可以在指定配置文件的情况下同时实现互补
代码语言:javascript复制java -jar spring-boot-configuration-0.0.1-SNAPSHOT.jar --spring.config.additional-location=/Users/jgnan/Practice/March/application.yml
参考文档Spring Boot 官方文档 External Application Properties
七、配置文件的加载顺序
配置文件官方文档 Spring Boot支持多种外部配置方式,优先级从高到低分别为
- 命令行参数
- 虚拟机参数
- 操作系统参数
- JAR包外部的带spring.profile的application-{profile}.properties或yml格式的配置文件
- JAR包内部的带spring.profile的application-{profile}.properties或yml格式的配置文件
- JAR包外部的不带spring.profile的application-{profile}.properties或yml格式的配置文件
- JAR包内部的不带spring.profile的application-{profile}.properties或yml格式的配置文件
- @Configuration类上的@PropertySource指定的配置文件
- SpringApplication.setDefaultProperties指定的默认属性
优先加载profile命令的配置文件,优先从外向内寻找
八、Spring Boot自动配置项
Spring Boot配置文件中所有的配置项可以参考官方文档 Common Application Properties
从源码中查看配置项
Spring Boot所包含的自动配置类都在org.springframework.boot.autoconfigure包下的META-INF/spring.factories中
进入DispatcherServletAutoConfiguration自动配置类的源码中,该类上标注了@AutoConfigureAfter注解
代码语言:javascript复制@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
进入ServletWebServerFactoryAutoConfiguration类
代码语言:javascript复制@EnableConfigurationProperties(ServerProperties.class)
该类标注了@EnableConfigurationProperties注解,指定的XxxProperties类就包含了配置项
DispatcherServletAutoConfiguration 和ServletWebServerFactoryAutoConfiguration使用的是相同的配置
相关注解的作用
- @Configuration:表示这是一个配置类,同以往的XML配置文件一样,可以往容器中注册组件或者Bean
- @EnableConfigurationProperties:启动指定类的ConfigurationProperties功能,将配置文件中对应的值和XxxProperties绑定起来
- @AutoConfigureAfter:在某个自动配置类配置后在执行自动配置
- @ConfigurationProperties:从配置文件中获取指定的值和Bean的属性进行板顶
所有的配置项都来自自动配置类中启用的XxxProperties类,也就说说一旦自动配置类生效,这个配置类就会给容器中注册各种组件,这些组件的属性都是从@EnableConfigurationProperties注解指定的XxxProperties类中获取的,这些类里面的每一个属性和配置文件是一一绑定的
总结
- XxxxAutoConfiguration是自动配置类,往容器中注册组件
- XxxProperties封装了配置文件中的相关属性
- @Conditional派生注解
@Conditional派生注解        | 作用(判断是否满足当前指定的条件)       |
---|---|
@ConditionalOnJava | 判断系统Java版本是否符合要求 |
@ConditionalOnBean | 判断容器中是否存在指定的Bean |
@ConditionalOnMissingBean | 判断容器中是否不存在指定的Bean |
@ConditionalOnExpression | 判断是否满足SpEL表达式 |
@ConditionalOnClass | 判断系统中是否有指定的类 |
@ConditionalOnMissingClass | 判断系统不含有指定的类 |
@ConditionalOnSingleCandidate | 判断容器中的Bean是否只有一个或者是首先的Bean |
@ConditionalOnProperty | 判断指定的属性是否有指定的值 |
@ConditionalOnResource | 判断类路径下是否存在指定的资源文件 |
@ConditionalOnWebApplication | 判断当前是否是Web环境 |
@ConditionalOnNotWebApplication | 当前是否不是Web环境 |
@ConditionalOnJndi | 当前Jndi存在指定项 |
如何查看启用和未启用的配置
官方配置文档中的第一项是debug,设置debug=true时控制台会输出哪些配置类启用
代码语言:javascript复制debug: true
启动主程序
控制台会打印出当前应用程序中所有激活的和未激活的配置