Spring 全家桶之 Spring Boot 2.6.4(二)- Configuration(Part B)

2022-08-24 14:35:59 浏览数 (1)

三、@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支持多种外部配置方式,优先级从高到低分别为

  1. 命令行参数
  2. 虚拟机参数
  3. 操作系统参数
  4. JAR包外部的带spring.profile的application-{profile}.properties或yml格式的配置文件
  5. JAR包内部的带spring.profile的application-{profile}.properties或yml格式的配置文件
  6. JAR包外部的不带spring.profile的application-{profile}.properties或yml格式的配置文件
  7. JAR包内部的不带spring.profile的application-{profile}.properties或yml格式的配置文件
  8. @Configuration类上的@PropertySource指定的配置文件
  9. 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派生注解&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;

作用(判断是否满足当前指定的条件) &emsp;&emsp;&emsp;&emsp;&emsp;

@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

启动主程序

控制台会打印出当前应用程序中所有激活的和未激活的配置

0 人点赞