大数据、Java EE 学习资料请关注 B 站:https://space.bilibili.com/204792350

SpringBoot 配置解析

配置文件

全局配置文件,名称固定写法:

  • application.properties
  • application.yaml

YAML

一种以数据为中心的标记语言,适合作为配置文件存在;

比起 properties,结构上更适合阅读,具备良好的可视化。

server:
	port: 8090

基本语法

  • 缩进不同代表层级
  • 仅使用空格作为缩进
  • 缩进空格不限制,但是同级元素必须相同
  • 大小写敏感

最基本的语法:

key: value

注意:值的前面必须至少保留一个空格

支持数据结构

  • 对象:键值对的集合

    • 普通写法:

      key: 
      	value1: 123
      	value2: 456
      	vlaue3: 789
      
    • 行内写法:

      key: {value1: 123, value2: 456, value3: 789}
      
  • 数组:一组按次序排列的值

    • 使用 - 方式:

      array: 
      	- 123
      	- 456
      	- 789
      
    • 行内方式:

      array: [123,456,789]
      
  • 字面量:单个的、不可再分的值

    • 字符串默认不需要加引号,特殊情况需要处理的按引号不同,处理方式不同:
      • 单引号:转义其中的特殊字符
      • 双引号:不转义其中的特殊字符
    • 字符串可以多行形式,但是从第二行开始必须要有单个空格开头
  • 支持复合结构

    • 不同数据结构内可以嵌套其他数据结构

文档

yaml 单个文件内可以区分不同配置区域,使用 --- 隔开出多个配置区域:

server:
  port: 8080
---
server:
  port: 8081

占位符

在配置文件中,可以支持默认值:

person.age=${age:18}

在 age 不存在的时候,会将 18 作为值。

同时,可以引用当前配置文件中已定义的配置值:

person.age=18
person.dog.age=${person.age}

随机数值:

SpringBoot 提供了几种随机值:

  • random.int
  • random.int(vlaue, [max])
  • random.long
  • random.long(min, [max])
  • random.uuid
  • random.value

注入配置

支持两种方式注入配置信息:

  • @ConfigurationProperties
  • @Value

但是,两种方式都需要添加 @Component 注解,保证类是 Spring 的容器 Bean。

@ConfigurationProperties

本地定义的类,若是若是需要外部另外配置的话,可以将其作为一种配置存在,定义在配置文件中,可灵活变化。

要完成这个要求的话,需要在类上面添加两个组件:

  • @Component
  • @ConfigurationProperties

作为 Spring 组件的类才满足作为外部注入配置的条件之一;

同时,一个类中是需要有对应的 setXXX() 方法,否则是无法完成注入的。

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    //......
}

在 @ConfigurationProperties 中,定义配置的前缀,将正确的配置注入类中。

@Value

@Component
public class Person {
    @Value("19")
    private Integer age;
    @Value("person")
    private String name;
}

两种方式的区别

区别@ConfigurationProperties@Value
功能批量注入单独注入
SpEl 语法不支持支持
松散绑定支持不支持
JSR 303 数据校验支持不支持
复杂类型支持不支持

解析:

  • SpEl 语法:指的是,可以进行简单运算

    @Value("#{1+2}")
    private Integer age;
    
  • 松散绑定:对待大小变量转换为配置的名称,要求上没有太严格,可多种格式:

    • Person 类属性名:firstName

    • 四种格式:

      • person.firstName
      • person.first-name
      • person.first_name
      • person.FIRST_NAME
      #person.firstName=123
      #person.first-name=123
      #person.first_name=123
      #person.FIRST_NAME=123
      

数据校验

使用 @ConfigurationProperties 注解的方式注入配置,可以使用 Spring 的 @Validated 数据校验注解;

@Component
@Validated
@ConfigurationProperties(prefix = "person")
public class Person {
    @Email
    private String firstName;
}

实例中,@Email 注解的属性,必须是邮箱格式,否则抛出异常。

定义本地配置元数据

在类的上面加上两个注解:

  • @Component
  • @ConfigurationProperties

需要加载一个 jar 包依赖,之后,本地类若是需要注入的话,会有相应的提示。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

@PropertySource 与 @ImportResource

@PropertySource

加载指定的配置文件,无需从全局配置文件中获取无关 Spring 的值。

@Component
@ConfigurationProperties(prefix = "person")
@PropertySource(value = {"classpath:person.properties"})
public class Person {
    // ......
}

@ImportResource

SpringBoot 默认不会加载 .xml 方式定义的 bean,若是需要以这种方式定义 bean,那么需要将其导入:

@ImportResource(locations = {"classpath: beans.xml"})
@SpringBootApplication
public class LearningApplication {

    public static void main(String[] args) {
        SpringApplication.run(LearningApplication.class, args);
    }
}

这样,在 beans.xml 文件内定义的 bean,就会被加载到 ioc 容器中。

支持多个配置文件同时导入,locations 是一个数组类型。

定义 Bean

给 ioc 容器中注册组件,有两种方式,一种是 xml 配置文件,另外就是全注解方式。

xml 就不说了,在 SpringBoot 中,使用的很少。这种方式需要使用 @ImportResource 注解,标注在主程序类上面。

以下是 SpringBoot 全注解方式给 ioc 容器注册组件:

@SpringBootConfiguration
public class AdminConfiguration {
    @Bean
    public Admin admin() {
        return new Admin();
    }
}

可以使用 @Configuration 组件表示类是一个注解类,这是 Spring 底层支持的。

在 SpringBoot 中,可以使用 @SpringBootConfiguration 组件,这是 SpringBoot 特有的。

搭配 @Bean ,可以将一个方法的返回值作为 bean,注册到 ioc 容器中,默认的组件 id 是方法名称。

多环境支持

激活不同环境有两种方式:

  • 在配置文件中:spring.profiles.active=dev
  • 命令行方式:--spring.profiles.active=dev
  • JVM 参数:-Dspring.profiles.active=dev

Profile 方式

SpringBoot 支持在不同环境下,使用不同的配置文件,默认的配置文件:application.properties

激活环境配置文件,在 application.properties 配置文件中指定。

格式:application-{自定义}.yml/properties

例如:application-dev.yml/properties

激活:

spring.profiles.active=dev

此时,application-dev.yml/properties 文件就生效了。

文档块方式

yaml 语法支持单个文件内,区分不同的配置区域。spring-boot 就支持这种方式。

例如:

server:
    port: 8090
spring:
    profiles:
        active: dev
---
spring:
    profiles: dev
server:
    port: 8091
---
spring:
    profiles: prod
server:
    port: 8092

加载顺序

SpringBoot 支持不同位置,不同形式的配置文件或者参数,一共 17 种,优先级由高到低。

方式描述
全局配置文件$HOME/.config/spring-boot:这个位置配置文件适用于整个引用程序
spring-boot-devtools.properties
spring-boot-devtools.yaml
spring-boot-devtools.yml
@TestPropertySource注解标注的类
测试的属性在@SpringBootTest和测试注释中提供,用于测试应用程序的特定部分。
命令行参数直接对某些参数指定
来自 SPRING_APPLICATION_JSON(内嵌在环境变量或系统属性中的JSON)的属性
ServletConfig 初始化参数
ServletContext 初始化参数
来自java的JNDI属性:comp/env
Java系统属性(System.getProperties())
操作系统环境变量
RandomValuePropertySource,其属性仅为:random.*
打包 jar 之外的特定于概要文件的应用程序属性(application-.properties和YAML变量)profile 是不同环境使用的配置
打包在 jar 中的特定于概要文件的应用程序属性(application-.properties和YAML变量)
打包 jar 之外的应用程序属性(Application.properties和YAML变体)
打包在 jar 中的应用程序属性(Application.properties和YAML变体)
@Configuration 类上的 @PropertySource 注释请注意,在刷新应用程序上下文之前,这些属性源不会添加到环境中
现在配置某些属性(如 logging.* 和 spring.main.* 等)无效,这些属性在刷新开始之前就会被读取
默认属性(通过设置 SpringApplication.setDefaultProperties 指定)

方式有很多种,但是常用的就那么几种,使用 profile 配置不同环境的配置文件,还有运行时候,通过命令行参数覆盖已有参数,又或者在 jar 所在位置添加外部配置文件,最直接的在全局配置文件定义。

指定配置文件

java -jar xxx.jar --spring.config.location="/home/config/application.properties"

配置原理

  • 从主程序入口,@SpringBootApplication 注解
    • 其中有一个 @EnableAutoConfiguration 注解,表示启动自动配置
  • @EnableAutoConfiguration 注解中,导入了其他组件:AutoConfigurationImportSelector.class
  • AutoConfigurationImportSelector
    • 有几个重要的方法:
      • process:处理需要自动配置的组件
      • getAutoConfigurationMetadata:获取自动配置元数据
        • AutoConfigurationMetadataLoader,使用 AppClassLoader 类加载器获取 META-INF/spring-autoconfigure-metadata.properties 内容
        • 实际上就是 spring-boot-autoconfigure-*.*.*.RELEASE.jar 这个依赖
      • getAutoConfigurationEntry:对获取的自动配置条目进行过滤,删除重复等等操作,最后以 List 数据类型返回满足条件的组件全类名

示例,以 HttpEncodingAutoConfiguration 为例:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
    //......
}

解析:

  • 类必须是配置类
  • 通过 @EnableConfigurationProperties(HttpProperties.class)
    • 启用 HttpProperties bean 属性绑定配置值
    • 之后可以通过 HttpProperties 来依赖注入,获取其中的属性值
    • 这样做的好处就是,将配置 bean 与实际组件配置区分开
  • @ConditionalOnWebApplication 判断是否 Web 应用
  • @ConditionalOnClass 判断其中所需类是否在当前类路径下
  • @ConditionalOnProperty 判断所需添加是否满足

当 @Conditional*** 等之类的注解都满足时候,当前的自动配置类才会生效,否则无效。

小结

1)SpringBoot 内置了大量的自动配置类,所以可以从里面找到可能存在我们需要的依赖

2)一个自动配置类中会注册多个组件到 IOC 容器中

3)自动配置类会从 ***Properties 相关类中获取所需要的配置值,该类的值可以从 SpringBoot 配置文件中定义。

4)自动配置类会在满足条件的时候,才会生效,否则无效

5)通过自动配置类的方式,可以灵活的注册组件,例如说逻辑代码处理等等

6)自动配置类是 SpringBoot 的主要精髓所在,若没有这样的动能,SpringBoot 所提倡的约定优先与配置则不成立

扩展

# Java   Spring   框架   SpringBoot  

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×