SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、

YML

SpringBoot 使用一个全局的配置文件, 配置文件名是固定的
    •application.properties
    •application.yml
 
配置文件的作用: 修改SpringBoot自动配置的默认值 SpringBoot 在底层都给我们自动配置好;
 

值的写法

字面量:普通的值(数字,字符串,布尔)
 
    k: v :字面直接来写;   字符串默认不用加上单引号或者双引号
        "" :双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi" :输出; zhangsan 换行 lisi
 
        '' :单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’ :输出; zhangsan \n lisi
 

对象、Map(属性和值)(键值对):

friends: 
  lastName: zhangsan 
  age: 20

 行内写法

friends: {lastName: zhangsan,age: 18}
数组( List Set ):
pets: 
   ‐ cat 
   ‐ dog 
   ‐ pig

 行内写法

pets: [cat,dog,pig]

配置文件值注入

person: 
 lastName: hello 
 age: 18 
 boss: false 
 birth: 2017/12/12 
 maps: {k1: v1,k2: 12} 
 lists: 
  ‐ lisi 
  ‐ zhaoliu 
 dog: 
  name: 小狗 
  age: 12

@ConfigurationProperties 该注解可以放在类上,也可以放在方法上。可以从注解说明中看到,当将该注解作用于方法上时,如果想要有效的绑定配置,那么该方法需要有@Bean注解且所属Class需要有@Configuration注解。

疑问:当有多个配置文件时,框架如何知道选择哪个配置文件中的prefix呢? 

/*** 将配置文件中配置的每一个属性的值,映射到这个组件中 
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; 
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射 
** 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; 
**/ 
@Component 
@ConfigurationProperties(prefix = "person") 
public class Person { 
  private String lastName; 
  private Integer age; 
  private Boolean boss; 
  private Date birth; 
  private Map maps; 
  private List lists; 
  private Dog dog; 
   
我们可以导入配置文件处理器,以后编写配置就有提示了。( 也有说当用到propertise和xml这种比较老的配置文件的时候才需要这个依赖。。。
 
 
    org.springframework.boot 
    spring‐boot‐configuration‐processor 
    true 

@Value获取值和@ConfigurationProperties获取值比较

SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第1张图片

如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用 @Value
如果说,我们专门编写了一个 javaBean 来和配置文件进行映射,我们就直接使用 @ConfigurationProperties
 

配置文件占位符  

     :  指定默认值

person.last‐name=张三${random.uuid} 
person.age=${random.int} 
person.birth=2017/12/15 
person.boss=false 
person.maps.k1=v1 
person.maps.k2=14 
person.lists=a,b,c 
person.dog.name=${person.hello:hello}_dog 
person.dog.age=15

Profile

server: 
  port: 8081 
spring: 
  profiles: 
    active: prod 

‐‐‐ 
server: 
  port: 8083 
spring: 
  profiles: dev 

‐‐‐ 

server: 
  port: 8084 
spring: 
  profiles: prod #指定属于哪个环境

配置文件加载位置

springboot 启动会扫描以下位置的 application.properties 或者 application.yml 文件作为 Spring boot 的默认配置文
 
    –file:./confifig/
    –file:./
    –classpath:/confifig/
    –classpath:/
 
优先级由高到底,高优先级的配置会覆盖低优先级的配置;

SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第2张图片

SpringBoot 会从这四个位置全部加载主配置文件( 无论最后用不用 ); 互补配置
 
我们还可以通过 spring.config.location 来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默 认加载的这些配置文件共同起作用形成互补配置;
 
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location =G:/application.properties
 

外部配置加载顺序

SpringBoot 也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会 形成互补配置
 
1. 命令行参数
所有的配置都可以在命令行上进行指定
 
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port =8087 --server.context-path =/abc
 
多个配置用空格分开; -- 配置项 =
 
2. 由 jar 包外向 jar 包内进行寻找;
优先加载带profifile (带profile是指配置文件中带有profile属性)
 
6.jar 包外部的 application-{profile}.properties application.yml( spring.profile) 配置文件
7.jar 包内部的 application-{profile}.properties application.yml( spring.profile) 配置文件
 

例子如下: 

SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第3张图片   

jar包外(然后路径条中  cmd  + java -jar spring-boot-02-confifig-02-0.0.1-SNAPSHOT.jar 即可)

3. 再来加载不带 profile
8.jar 包外部的 application.properties application.yml( 不带 spring.profifile) 配置文件
9.jar 包内部的 application.properties application.yml( 不带 spring.profifile) 配置文件
 

自动配置原理

SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第4张图片

@EnableAutoConfiguration 作用:
  • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件?
  • 可以查看selectImports()方法的内容; (该方法在AutoConfigurationImportSelector.class的父类中,该方法可以点出以下的内容)
  • List confifigurations = getCandidateConfifigurations(annotationMetadata, attributes);获取候选的配置
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);  // 获取候选配置
            configurations = this.removeDuplicates(configurations);
            Set exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.getConfigurationClassFilter().filter(configurations);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

其中   getCandidateConfigurations 如下

    protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

loadFactoryNames 辗转点进去如下

private static Map> loadSpringFactories(ClassLoader classLoader) {
        Map> result = (Map)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            HashMap result = new HashMap();

            try {
                Enumeration urls = classLoader.getResources("META-INF/spring.factories");  // 扫描所有jar包类路径下 META‐INF/spring.factories

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        String[] var10 = factoryImplementationNames;
                        int var11 = factoryImplementationNames.length;

                        for(int var12 = 0; var12 < var11; ++var12) {
                            String factoryImplementationName = var10[var12];
                            ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                                return new ArrayList();
                            })).add(factoryImplementationName.trim());
                        }
                    }
扫描所有jar包类路径下 META‐INF/spring.factories
把扫描到的这些文件的内容包装成 properties 对象
properties 中获取到 EnableAutoConfiguration . class 类(类名)对应的值,然后把他们添加在容器 中
 

SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第5张图片

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

SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第6张图片

每一个这样的 xxxAutoConfifiguration类 都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
 
  3 )、每一个自动配置类进行自动配置功能;
  4 )、以 HttpEncodingAutoConfifiguration Http 编码自动配置) 为例解释自动配置原理;
 
@Configuration //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件 
@EnableConfigurationProperties(HttpEncodingProperties.class) //启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把 HttpEncodingProperties加入到ioc容器中 
@ConditionalOnWebApplication //Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果 满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效 
@ConditionalOnClass(CharacterEncodingFilter.class) //判断当前项目有没有这个类 CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的 
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;

public class HttpEncodingAutoConfiguration { 

//他已经和SpringBoot的配置文件映射了 
private final HttpEncodingProperties properties;

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

@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取 
@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个组件?
public CharacterEncodingFilter characterEncodingFilter() { 
    CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();   
    filter.setEncoding(this.properties.getCharset().name()); 
    filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); 
    filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); 
    return filter;
 }

@Conditional派生注解

作用:必须是 @Conditional 指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第7张图片
 
自动配置类必须在一定的条件下才能生效;
我们怎么知道哪些自动配置类生效;
我们可以通过启用 debug=true 属性;来让控制台打印自动配置报告 ,这样我们就可以很方便的知道哪些自动配置类生效;
 
SpringBoot配置---YML写法、配置文件值注入、占位符、profile、配置文件加载位置(内外)、自动配置原理、@Conditioal、_第8张图片
Positive matches:
-----------------

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

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)

   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)
      - @ConditionalOnMissingBean (types: io.r2dbc.spi.ConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

     (.........)
Negative matches:
-----------------

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

   AopAutoConfiguration.AspectJAutoProxyingConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)

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

   BatchAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.springframework.batch.core.launch.JobLauncher' (OnClassCondition)

   CacheAutoConfiguration:
      Did not match:
         - @ConditionalOnBean (types: org.springframework.cache.interceptor.CacheAspectSupport; SearchStrategy: all) did not find any beans of type org.springframework.cache.interceptor.CacheAspectSupport (OnBeanCondition)
      Matched:
         - @ConditionalOnClass found required class 'org.springframework.cache.CacheManager' (OnClassCondition)

           (....................)

 

你可能感兴趣的:(Java基础)