二、SpringBoot配置-简述配置加载原理

springboot使用一个全局配置文件

  • application.properties
  • application.yml

配置文件放在src/main/resources目录或者类路径/config下
.yml是YMAL语言的文件,以数据为中心,比json、xml等更适合作配置文件
全局配置文件的可以对一些默认配置值进行修改
配置文件的作用:修改springboot自动配置的默认值,因为springboot在底层都给我们自动配置好,所以通过配置文件修改默认值

Yaml基本语法:

1、key: value 表示一对键值对(空格必须有)
以空格的缩进控制层级关系,只要是左对齐的一列数据都是同一层级的

server:
    port: 8080

属性和值也是大小写敏感;
2、值的写法
字面量:普通的值(数字、字符串、布尔):
k: v:字面直接来写;
字符串默认不用加上单引号或者双引号
“”:双引号;不会转移字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name:”zhangsan\nlisi”:输出 zhangsan 换行 lisi
‘’:单引号,回转仪特殊字符,特殊字符最终只是一个普通的字符串数据
name:‘zhangsan\nlisi’:输出zhangsan\nlisi
对象、map(属性和值):
k: v: 在下一行来写对象的属性和值的关系;注意缩进
对象还是k:v的方式

fridends:
    lastName: zhangsan
    age: 20

行内写法:

friends: {lastName: zhangsan, age: 18}

数组(List、Set):
用- 值表示数组中的一个元素

pets:
    - cat
    - dog

行内写法:

pets: [cat,dog]
获取配置文件值(配置文件注入)

1、使用yml配置文件注入
yml配置文件:

person:
  lastName: zhangsan
  age: 18
  boss: false
  birth: 2020/04/18
  maps: {k1: v1, k2: v2}
  list:
    - lisi
    - hahaha
  dog:
    name: gougou
    age: 2

bean Person类:

/**
 * 将配置文件中的每一个属性中的值,映射到这个组件中
 * @ConfigurationProperties:告诉springboot将本类中的所有属性和配置文件中相关配置进行绑定
 *      perfix = "person" 配置文件中哪个下面的配置进行一一映射
 *
 *  只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能
 *  @Component注入到容器中
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastName;
    private int age;
    private Boolean boss;
    private Date birth;


    private Map<String, Object> maps;
    private List<String> list;
    private Dog dog;

我们可以导入配置文件处理器,以后编写配置就会有提示了:

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

2、用properties注入
改在properties中进行配置是一样可行的,但需要注意编码问题,idea默认使用utf-8编码,而properties需要ASCII编码,所以需要在idea的设置-file encoding中勾选将properties转为ascii
在这里插入图片描述
3、使用@Value注入:

@Value("${person.last-name})  //在配置文件中拿值
private String lastName;
@Value("#{11*2}")
private int age;
@Value("false")
private Boolean boss;

用@Value和@ConfigurationProperties 的区别

ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散绑定(松散语法)支持不支持
SpEL不支持支持
JSR303数据校验支持不支持
复杂类型封装支持不支持

配置文件yml还是properties都能获取到值;
如果只是在某个业务逻辑中获取某项值,可以用@Value,如果专门编写了JavaBean和配置文件进行映射,就要用ConfigurationProperties
4、数据校验

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
    //@Value("${person.last-name}")
    @Email
    private String lastName;
    //@Value("#{11*2}")
    private int age;
    //@Value("false")
    private Boolean boss;
    private Date birth;


    private Map<String, Object> maps;
    private List<String> list;

@PropertySource和@ImportResource

@PropertySource:加载指定的配置文件

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

@ImportResource :导入Spring的配置文件,让配置文件里面的内容生效

SpringBoot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;
想让Spring配置文件生效,要将@ImportResource标注在一个配置类上

@ImportResource(locations = {"classpath:bean.xml”})
//导入配置文件才能生效

原配置文件内容

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="helloService" class="com.study.springbootconfig.service.HelloService"></bean>
</beans>

springboot推荐的给容器中添加组件的方式:推荐使用全注解的方式
1、配置类====使用配置文件
2、使用@Bean给容器中添加组件:

/**
 * @Configuration 指明当前类是一个配置类替代之前的spring配置文件
 * 在配置文件中用<bean></bean>标签添加组件
 */
@Configuration
public class MyConfig {
    //将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
    @Bean
    public HelloService helloService(){
        System.out.println("配置类给容器中添加组件了");
        return new HelloService();
    }
}
配置文件占位符

1、随机数:

${random.value} 、${random.int}、${random.long}、${random.int(10)}、${random.int[1024,6666]}

2、占位符获取之前配置的值,如果没有可以使用:指定默认值

person.last-name=张三${random.uuid}
person.age=${random.int(1,100)}
person.birth=2011/12/12
person.boss=false
person.maps.k1=v1
person.maps.k2=123
person.list=a,b,c
person.dog.name=${person.hello:hello}dog
person.dog.age=11
profile

profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境
1、多profile文件
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
2、yml支持多文档块方式

server:
  port: 8081
spring:
  profiles:
    active: prod
---
server:
  port: 8083
spring:
  profiles: dev
---
server:
  port: 8084
spring:
  profiles: prod

3、激活指定profile
1)在配置文件中指定:spring.profiles.active=dev
2)命令行方式:
在测试的时候传参指定
在这里插入图片描述
—spring.profiles.active=dev
打包的时候,使用spring.profiles.active指定
3)虚拟机参数:
-Dspring.profiles.active=prod
在这里插入图片描述

配置文件加载位置

springboot启动会扫描以下位置的application.properties/yml文件作为默认配置文件
加载顺序由高到低,高优先级配置覆盖低优先级:

  • file:./config/
  • file: ./
  • classpath:/config/
  • classpath:/
    springboot会在这四个位置全部记载配置文件,互补配置

还可以通过spring.config.location来改变默认的配置文件位置
不能再开发调试的时候用,是项目打包好以后,可以使用命令行的参数的方式,启动项目的时候指定配置文件的新位置;指定配置文件和默认加载的这些配置文件会共同起作用,互补配置

外部配置加载顺序

spring也可以从以下位置加载配置,优先级由高到低,覆盖并互补
1、命令行参数
2、来自java:conp/env的NDI属性
3、jsva系统属性(System.getProperties())
4、操作系统环境变量
5、RandomValuePropertySource配置的random.*属性值
优先加载带profile,再加载不带profile的,都是由jar包外向jar包内寻找
6、jar包外部的application-{profile}.properties或application.yml(带spring.profie)的配置文件
7、jar包内部的application-{profile}.properties或application.yml(带spring.profie)的配置文件
8、jar包外部的application.properties或application.yml(不带spring.profie)的配置文件
9、jar包内部的application.properties或application.yml(不带spring.profie)的配置文件

10、@Configuartion注解类上的@PropertySource
11、通过SpringApplication.setDefaultProperties指定的默认属性
所有的配置加载来源参考官网文档

自动配置原理

1、Springboot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2、@EnableAutoConfiguration作用:

  • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件
  • 可以查看selectImports方法的内容
  • List configurations = this.getCandidateConfigurations(annotationMetadata, attributes) 获取候选的配置
SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
//扫描所有jar包路径 META-INF/spring.factories
//把扫描到的这些文件的内容包装成properties
//从properties中获取到EnableAutoConfiguration.class对应的值,然后把它们添加在容器中

即 将类路径下的 META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加到了容器中。
每一个 xxxAutoConfiguration类都是容器中的一个组件都计入到容器中,用他们做自动配置
3、每一个自动配置类进行自动配置功能
4、 以HttpEncodingAutoConfiguration为例解释自动配置原理

@Configuration(  //表示这是一个配置类,以前写的配置文件一样,也可以给容器中添加组件
    proxyBeanMethods = false
)
@EnableConfigurationProperties({HttpProperties.class})//启用ConfigurationProperties功能;将配置文件中对应的值和HttpProperties帮顶起来
@ConditionalOnWebApplication( //spring底层有一个Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效。 这个意思就是判断当前应用是否为web应用,如果是,当前配置类生效
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})//判断当期项目有没有这个类 CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
) //配置文件中是否存在 spring.http.encoding.enabled;如果不存在,判断也是成立的,即使我们配置文件中不配置spring.http.encoding.enabled,也是生效的

public class HttpEncodingAutoConfiguration {
    //他已经和springboot的配置文件映射了
    private final Encoding properties;
    //只有一个有参构造器,参数的值就会从容器中拿;并把HttpProperties加入到ioc容器中
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }

 
    @Bean  //给容器中添加一个,这个组件的某些值需要从properties中获取
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }

根据当前的条件判断,决定这个配置类是否生效
一旦这个配置类生效,这个配置类就会给容器添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的

5、所有在配置文件中能配置的属性都是在xxxProperties类中的封装者;配置文件能配置什么就可以参照某个功能对应的属性类

@ConfigurationProperties(   
 prefix = "spring.http"
) // 从配置文件中获取指定的值和bean的属性进行绑定
public class HttpProperties {
    private boolean logRequestDetails;
    private final HttpProperties.Encoding encoding = new HttpProperties.Encoding();

精髓:
1)、springboot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有springboot默认写好的自动配置类
3)、我们再来看这个自动配置类到底配置了哪些组件;(只要我们组件有,我们就不需要再来配置了)
4)、给容器中自动配置类自动添加组件的时候,会从properties中获取某些属性的时候,我们就可以在配置文件中指定这些属性的值

xxxAutoConfiguration:自动配置类,他会给容器中添加组件也会有对应的xxxProperties,封装配置文件中相关的属性
配置细节
1、@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional条件成立才给容器中添加组件,配置里面的所有内容才生效。
自动配置类必须在一定的条件下才能生效

怎么知道自动配置类是否生效:在配置文件中配置debug=true,开启debug模式,运行时控制台就会打印自动控制报告就可以知道哪些自动配置类生效

============================
CONDITIONS EVALUATION REPORT
============================




Positive matches: //(自动配置类启用的)
-----------------


   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)


Negative matches: //没有启动,没有匹配成功的自动配置类
-----------------


   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot的自动配置原理是基于条件注解和Spring Boot Starter机制实现的。 首先,Spring Boot会扫描所有的依赖包中的`META-INF/spring.factories`文件,该文件中定义了各个Starter的自动配置类。Spring Boot会读取这些自动配置类,并根据条件注解来判断是否需要进行自动配置。 条件注解是Spring Boot中用于控制自动配置的核心机制。通过在自动配置类上添加条件注解,可以根据不同的条件来决定是否启用自动配置。常用的条件注解包括`@ConditionalOnClass`、`@ConditionalOnBean`、`@ConditionalOnProperty`等。 `@ConditionalOnClass`注解用于判断某个类是否在类路径中存在,如果存在则启用自动配置。`@ConditionalOnBean`注解用于判断某个Bean是否存在,如果存在则启用自动配置。`@ConditionalOnProperty`注解用于判断某个配置属性是否满足条件,如果满足则启用自动配置。 当满足条件时,Spring Boot会自动配置相应的Bean,并将其添加到Spring容器中。这样,我们就可以直接使用这些自动配置的Bean,而无需手动进行配置。 总结起来,Spring Boot的自动配置原理是通过条件注解和Spring Boot Starter机制来实现的。条件注解用于判断是否需要进行自动配置,而Spring Boot Starter则提供了一种约定的方式来组织和管理自动配置。这种机制使得开发者可以更加方便地使用和扩展Spring Boot的自动配置功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值