1.配置文件加载位置

Springboot启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件

优先级由高到低,高优先级配置会覆盖低优先级的配置:
Spring boot会从这四个位置全部加载主配置文件夹;互补配置

  • -file:./config
  • -file:./
  • -classpath:/config
  • -classpath:/

通过Spring.config.location来改变默认的配置文件位置(打包成功的项目需要需改部分配置时只需要编写少量的配置把项目重新启动通过Spring.config.location加载新改的配置,不需要把整个项目改变再打包)

项目打包好以后可以使用命令行参数的形式,启动项目时来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;


2.外部配置加载顺序

SpringBoot也可以从以下位置加载配置;优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置

  1. 命令行参数:java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=81 --spring.context-path=/abc 多个配置用空格分开;–配置项=值
  2. 来自java:comp/env的JNDI属性
  3. Java系统属性(System.getProperties())
  4. 操作系统环境变量
  5. RandomValuePropertySource配置的random.*属性值

由jar包外向jar包内进行寻找

优先加载带profile

  1. jar包外部的application-{profile}.properties或者application.yml(带spring.profile)配置文件
  2. jar包内部的application-{profile}.properties或者application.yml(带spring.profile)配置文件
  3. jar包外部的application.properties或者application.yml(不带spring.profile)配置文件
  4. jar包内部的application.properties或者application.yml(不带spring.profile)配置文件
  5. @Configuration注解类上的@PropertySource
  6. 通过SpringApplication.setDefaultProperties指定的默认属性

3.自动配置原理

1.自动配置原理

配置文件到底能写什么?怎么写?自动配置原理:

自动配置原理(关键)

  1. spring boot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
  2. @EnableAutoConfiguration的作用:
  • 利用AutoConfigurationImportSelector给容器中导入组件?
  • 可以查看selectImports()的方法的内容即可知道导入了那些组件;
  • List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包所有类路径下的META-INF/spring.factories
把扫描到的这些文件的内容全部包装成properties对象
从properties获取到EnableAutoConfiguration.class这个类(类名)对应的值,然后把他们添加在容器中

将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
.
.
.
.
.
.

每一个这样的xxAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来做自动配置;
3. 每一个自动配置类进行自动配置功能

  1. HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理:
//表示这是一个配置类,类似以前写的配置文件,也可以给容器中添加组件
@Configuration(
    proxyBeanMethods = false
)

//启用指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来,并把HttpEncodingProperties加入到IOC容器中
@EnableConfigurationProperties({ServerProperties.class})

//Spirng底层有一个@Conditional注解,根据不同的条件,可以自己进行条件判断,如果满足整个配置类中的配置就会生效;作用:判断当前应用是否是web应用,如果是那么当前配置类生效
@ConditionalOnWebApplication(
    type = Type.SERVLET
)

//作用:判断当前项目中是否有这个类CharacterEncodingFilter;Spring Mvc中进行解决乱码的过滤器
@ConditionalOnClass({CharacterEncodingFilter.class})

//判断配置文件中是否有某个配置server.servlet.encoding,如果不存在判断成立,即使配置文件中不配置server.servlet.encoding也是默认生效
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)


public class HttpEncodingAutoConfiguration {

    //他已经和SpringBoot的配置文件映射了是在获取server.servlet.encoding中的值的
    private final Encoding properties;

    //只有一个有参构造器的情况下,参数的值就会从容器中拿
    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

//给容器中添加一个组件,把这个filter添加过去,这个组件中的有些熟悉需要从properties中获取
    @Bean
    //判断容器中没有这个组件,如果没有就添加这个组件
    @ConditionalOnMissingBean(CharaterEncodingFilter.class)
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
        return filter;
    }

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

我们能配置的属性都是来源于这个功能的properties

  1. 所有在配置文件能配置的属性都是在xxxxProperties类中封装着;配置文件能配置什么就可以参照某个功能对应的这个属性类
  • 例如HttpEncodingAutoConfiguration有一个@ConfigurationProperties(prefix = “server.servlet.encoding”)注解从配置文件中获取指定的值和bean的属性进行绑定

精髓:

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

xxxxAutoCOnfiguration:自动配置类
给容器中添加组件
xxxxProperties:封装配置文件中的相关属性

2.细节

1.@Conditional派生注解(Spring注解版原生的Conditional作用)

作用:必须是@Conditional指定的条件成立,才能给容器中添加组件,配置类的里面所有内容才生效

SpringBoot扩展了很多@Conditional注解

自动配置类必须在一定条件下才能生效;

那么如何知道那些自动配置类生效呢?

我们可以在application.properties中通过启用debug=true属性,来让控制台打印自动配置报告,这样就可以知道哪些自动配置类生效:

positive match:自动配置类启用的,匹配上了

negativ match:自动配置类没有启用的,没有匹配上