SpringBoot (一) 入门、配置、自动配置源码剖析理解

文章目录

  • 0 Spring Boot
  • 1 Overview
    • 1.1 Introduce
      • **Spring**
      • SpringBoot
      • 微服务
    • 1.2 快速上手
      • Hello World
      • pom.xml
      • starters 场景启动器
    • 1.3 自动配置-原理1
      • **@SpringBootApplication**内部结构
      • 结合资料
    • 1.4 快速创建项目
    • 1.5 单元测试
    • 1.6 添加组件
  • 2 Configuration
    • 2.0 配置文件加载
      • 位置
      • 外部配置加载顺序
    • 2.1 YAML
      • **基本语法**
      • 对象、Map
      • 数组 List Set
    • 2.2 获取配置文件中的值
      • 从YAML
      • 从properties
      • 还有一种方法: @Value + @PropertySource(..)
      • 两种方式对比
      • 向SpringBoot程序中添加组件
      • 其他补充
    • 2.3 配置文件占位符
    • 2.4 Profile
      • 1 多Profile文件
      • 2 YAML 多文档块
      • 激活指定profile的方式
    • 2.5 自动配置-原理2
      • 举例理解
      • **个人的理解, 也是给他人讲解时的白话:**
      • 精髓
      • @Conditional...派生注解
      • 配置过程的日志输出

0 Spring Boot

前言

  • 主要是作为个人笔记, 特别熟练知识的可能会无意识跳过或者淡化. 大多数是有用的文字.
  • 一些可以复用的章节, 例如各种配置的章节, 其实是可以在标题上加★来标识的.
  • 借鉴B站狂神老师和尚硅谷雷老师的课程, 源于官方文档

Document Directory

  • 是官网文档标题目录

水平暂时远做不到翻译文档, 就把官方文档的目录拿来学习一下英语

version 2.2.0

  1. Spring Boot Documentation
    1. About the Documentation
    2. Getting Help
    3. First Steps
    4. Wording with Spring Boot
    5. Learning about Spring Boot Features
    6. Moving to Production
    7. Advanced Topics
  2. Getting Started
    1. Introducing Spring Boot
    2. System Requirements
    3. Installing Spring Boot
    4. Developing Your First Spring Boot Application
    5. What to Read Next
  3. Using Spring Boot
    1. Build Systems
    2. Structuring Your Code
    3. Configuration Classes
    4. Auto-configuration
    5. Spring Beans and Dependendy Injection
    6. Using the @SpringBootApplicatior Annotation
    7. Running Your Application
    8. Developer Tools
    9. Packaging Your Application for Production
    10. What to Read Next
  4. Spring Boot Features
    1. SpringApplication
    2. Externalized Configuration
    3. Profiles
    4. Logging
    5. Internationalization
    6. JSON
    7. Developing Web Applications
    8. RSocket
    9. Security
    10. Working with SQL Databases
    11. Wording with NoSQL Technologies
    12. Caching
    13. Messaging
    14. Calling REST Services with RestTemplate
    15. Calling REST Services with WebClient
    16. Validation
    17. Sending Email
    18. Distributed
    19. hazelcast
    20. Quartz Scheduler
    21. Task Execution and Scheduling
    22. Spring Integration
    23. Spring Session
    24. Monitoring and Management over JMX
    25. Testing
    26. WebSockets
    27. Web Services
    28. Creating Your Own Auto-configuration
    29. Kotlin support
    30. What to Read Next
  5. Spring Boot Actuator: Production-ready Features
    1. Enabling Production-ready Features
    2. Endpoints
    3. Mnitoring and Management over HTTP
    4. Monitoring and Management over JMX
    5. Loggers
    6. Metrics
    7. Auditing
    8. HTTP Tracing
    9. Process Monitoring Cloud Foundry Support
    10. What to Read Next
  6. Deploying Spring Boot Applications
    1. Deploying to the Cloud
    2. Installing Spring Boot Applications
    3. What to Read Next
  7. Spring Boot CLI
    1. Installing the CLI
    2. Using the CLI
    3. Developing Applications with the Groovy Beans DSL
    4. Configuring the CLI with settings.xml
    5. What to Read Next
  8. Build Tool Plugins
    1. Spring Boot Maven Plugin
    2. Spring Boot Gradle Plugin
    3. Spirng Boot AntLib Module
    4. Supporting Other Build Systems
    5. What to Read Next
  9. “How-to” Guides
    1. Spring Boot Application
    2. Properties and Configuration
    3. Embedded Web Servers
    4. Spring MVC
    5. Testing With Spring Security
    6. Jersey
    7. HTTP Clients
    8. Logging
    9. Data Access
    10. Database Initialization
    11. Messaging
    12. Batch Applications
    13. Actuator
    14. Security
    15. Hot Swapping
    16. Build
    17. Traditional Deployment
  10. Appendices

知识结构

根据课程整理知识结构

  1. Overview
  2. Configuration
  3. Log
  4. Web
  5. Docker
  6. Data Access
  7. 启动配置原理
  8. 自定义starter
  9. Cache (以下高级)
  10. 消息中间件
  11. 检索
  12. 任务
  13. 安全
  14. 分布式
  15. 开发热部署
  16. 监控 (运维)

1 Overview

1.1 Introduce

Spring

为了解决企业级应用开发的复杂性而创建的框架, 可大幅简化开发

通过以下关键策略实现的简化:

  • 基于POJO, 轻量级最小侵入性编程 (对扩展开放)
  • IoC,DI和面向接口, 实现松耦合
  • 基于AOP实现声明式编程
  • 通过AOP和template(模板), 减少样式代码 (这点其实体会不够深)

SpringBoot

  • 用于简化Spring开发的框架

  • 整个Spring技术栈的大整合

  • J2EE开发一站式解决方案

优点

  • 快速创建+独立运行+易与主流工具集成 (其它主流框架) 的Spring项目
  • 使用"嵌入式Servlet容器", 无需打成.war
  • starter自动依赖和版本管理 (控制)
  • 大量"自动配置", 也可手动修改
  • 无需配置XML, 无代码生成, “开箱即用”
  • “运行时应用监控”, 准生产环境的
  • 与云计算天然集成

缺点

  • 入门容易, 精通难. 所以必须懂老Spring

个人认识

  • springcloud之后可能慢慢需要关注"服务网格"
  • “约定大于配置”, 不光要欢呼避免了配置, 同时也意味着约定也会变得更严格.
  • 一些鸡汤讲到, 不能光会"使用工具", 而忽视代码能力

微服务

架构演变:

from Dubbo Document

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySEpDbyc-1587907368465)(SpringBoot.assets/image-20200423161837334.png)]

概念

In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.

  • 2014, Martin Fowler提出概念

  • 是一种架构的风格, 一个应用可以是一组小型服务, 彼此通过轻量级的例如HTTP方式沟通

  • 每一个功能元素

1.2 快速上手

Hello World

学习环境

jdk 1.8 | maven 3.x | SpringBoot 1.5.9

maven的settings.xml中添加, 按照jdk1.8编译

传统步骤

  1. 新建普通maven

  2. 添加parent标签和web起步依赖

    <parent>
    	官网文档起步可以找到
    parent>
    <dependencies>
        <depen>depen>
    dependencies>
    
  3. 主程序类, org.zhangcl

    @SpringBootApplication	// 标注主程序类, 说明这是一个SpringBoot应用
    public class HelloWorldMainApplication{
        public static void main(Strring[] args){
            SpringApplication.run(HelloWorldMainApplication.class, args);
        }
    }
    
  4. 业务org.zhangcl.controller.HelloController.java

    @Controller
    public class HelloController{
        
        @RequestMapping
        @ResponseBody
        public String hello(){
            return "Hello, World!";
        } 
    }
    

部署

以前war包, 要在tomcat中, 但boot可以直接jar包

  1. 引入打包插件

      <build>
      <plugins>
       	<plugin>
           	...
    
     plugin>
       plugins>
      build>
    
  2. 使用Maven工具中有package功能

包中有内嵌的tomcat

pom.xml

<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>1.5.9.RELEASEversion>
    <relativePath/> 
parent>

parent

是SpringBoot的版本仲裁中心

它的父项目是spring-boot-dependencies

  • 管理各个可整合组件 (依赖) 的版本!
    • 导入这些依赖不需要写版本

    • spring-boot-starter-parent-1.5.9.RELEASE.pom, Ctrl+鼠标, 看parent, 能进来此文件. 其中管理很多重要内容, 如:

      • 很多依赖jar的版本号的仓库, 所以我们引入很多依赖不需要手动指定版本号
      • 过滤器对不同命名类型配置文件的过滤设置
    • 没有管理的依赖仍然需要手动规定版本号

starters 场景启动器

spring-boot-starter-web, "SpringBoot场景启动器"

web, 帮我们导入web模块正常运行所依赖的组件

SpringBoot将所有的功能场景抽取出来, 做成很多starters, 我们只需要在项目里引入这些starter项目场景的, 相关依赖回自动导入进来.

要用什么功能呢, 就导入对应场景启动器

1.3 自动配置-原理1

主启动类HelloApplication.java

@SpringBootApplication

  • 注解标注在某个类上, 说明是主启动类

@SpringBootApplication内部结构

纯结构

  • @SpringBootConfiguration
    • @Configuration()
  • @EnableAutoConfiguration
    • @AutoConfigurationPackage
      • @Import(AutoConfigurationPackages.Registrar.class)
        • AutoConfigurationImportSelector
          • List getCandidateConfigurations(...)
    • @Import(AutoConfigurationImportSelector.class)
      • AutoConfigurationImportSelector
  • @ComponentScan()
  • @ConfigurationPropertiesScan

解释

  • @SpringBootConfiguration
    • 标注在某个类上, 表示这是一个Springboot的配置类
    • @Configuration()
      • 表示这是一个配置类, 容器中的一个组件component
  • @EnableAutoConfiguration 开启自动配置功能
    • 以前我们呢需要配置的东西, boot帮我们自动配置了, 这个注解就是告诉boot开启自动配置功能
    • @AutoConfigurationPackage 自动配置包
      • 给容器多种导入(import)一个组件
      • @Import(AutoConfigurationPackages.Registrar.class)
        • 这个类决定导入哪个组件
        • AutoConfigurationImportSelector 自动配置导入选择器
          • 存在方法List getCandidateConfigurations(...)
    • @Import(AutoConfigurationImportSelector.class)
      • 给容器中导入组件
      • AutoConfigurationImportSelector
  • @ComponentScan()
  • @ConfigurationPropertiesScan

单独解释

@AutoConfigurationPackage 自动配置包的作用:

  • 有个getPackageName()

  • 将主配置启动类, 所在包及下边所有子包和组件扫描到Spring容器中

@Impor(EnableAutoConfigurationImportSelector.class)

  • 给容器中导入组件

  • Enable…Selector, 导入那些组件的选择器

  • 将所有需要导入的组件以全类名的方式返回, 添加到容器中!

    • 这是getPackageName()方法决定的
    • 如果不放在子包中, 会扫描不到!
    • 会给容器中导入很多很多自动配置类 (xxxAutoConfiguration), 就是给容器中导入这些场景需要的所有组件, 并配置好

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6n5rqT3O-1587907368468)(SpringBoot.assets/image-20200426132735168.png)]

这些自动配置类, 免去我们手动编写配置注入功能组件等的工作

结论:

  • SpringBoot启动时从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值, 将他们作为自动配置类导入容器中, 自动配置类就生效, 帮我们进行自动配置工作以前需要我们自己配置的东西, 自动配置类都帮我们做了

  • J2EE的整体整合解决方案和自动配置都在Spring-boot-autoconfigure-1.5.9.RELEASE.jar

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LOJomShJ-1587907368470)(SpringBoot.assets/image-20200426133939073.png)]

.run(…)

SpringApplication.run(当前类.class, args);

开启了一个服务

结合资料

参考资料

Craig Walls

这里我从中文版的作者Craig Walls先生的书中借鉴点内容, 帮助理解

简而言之, Spring Boot的自动配置是一个运行时 (更准确地说, 是应用程序启动时)的过程, 考虑了众多因素, 才决定Spring配置应该用哪个, 不该用哪个. 举几个例子, 下面这些情况都是Spring Boot 的自动配置要考虑的.

  • Spring的JdbcTemplate 是不是在Classpath里? 如果是, 并且有DataSource的Bean, 则自动配置一个JdbcTemplate的Bean
  • Thymeleaf是不是在Classpath里? 如果是, 则配置Thymeleaf的模板解析器、视图解析器以及模板引擎
  • SpringSecurity是不是在Classpath里? 如果是, 则进行一个非常基本的Web安全设置.

每当应用程序启动的时候, Spring Boot 的自动配置都要做将近200个这样的决定, 涵盖安全、集成、持久化、Web开发等诸多方面. 所有这些自动配置都是为了尽量不让你自己写配置.

秦疆老师

结论:

Spring Boot 所有的自动配置都是在启动的时候扫描并加载.

spring.factories, 所有的自动配置类都在这里, 不一定都生效, 需要判断条件是否成立, 只要导入了对应的starter, 就有对应的启动器, 有了启动器, 我们的自动配置才会生效!

大致流程如下:

  1. Spring Boot启动时, 从类路径下(META-INF/spring.factories)获取指定的值
  2. 将这些自动配置的类导入容器, 就会生效, 达到自动配置的效果
  3. 以前我们需要手动配置的东西, 现在Spring Boot代替我们做了
  4. 整个JavaEE, 解决方案和自动配置的信息都在spring-boot-autoconfigure-2.2.0.REALEASE.jar包下
  5. 它会把所有需要导入的组件, 以完整类名的方式返回, 然后这些组件会被加载到容器
  6. 容器中也会存在非常多的org.springframework.boot.autocofigure.xxx.xxx.*AutoConfiguration的文件, 就是这些类给容器导入了当下场景需要的所有组件. @Configuration, JavaConfig
  7. 有了自动配置类, 免去我们手动编写配置文件的操作

源码剖析

selectors

  • "自动导入配置选择器"类, 提供了"获取候选配置们()"方法

源码路径:

  • @SpringBootApplication
    • @AutoConfigurationPackage
      • @Import(AutoConfigurationPackages.Registrar.class)
        • AutoConfigurationImportSelector
          • 存在方法List getCandidateConfigurations(...)

candidateConfigurations

怎样知道"candidateConfigurations"在哪?

这个方法中有个参数是getBeanClassLoader()方法的返回值

  • getBeanClassLoader()
    • this.beanClassLoader() 底层给出一个路径META-INF/spring.factories

配置类们被spring.factories管理着

具体在哪能找到?

spring.factories具体在哪?

  • External Libraries
    • Maven:org.springframework.boot:spring-boot-autoconfigure:2.2.0.RELEASE
      • spring-boot-autoconfigure-2.2.0.RELEASE.jar
        • META-INF
          • spring.factories 保存了150+条候选配置类的位置url
            • Initializers
            • Application Listeners
            • Auto Configuration Import Listeners
            • Auto Configuration Import Filters
            • Auto Configure (最多)
            • Failure analyzers
            • Template availability providers

选例研习:

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 {
    ...
  1. 跳入源码后从@EnableConfigurationProperties(HttpProperties.class)

  2. 跳入HttpProperties.class

  3. 发现: 配置类实体和配置文件字段的绑定

    @ConfigurationProperties(prefix = "spring.http")
    public class HttpProperties {
        ...
    
  4. 发现@ConditionalOn…家族

    // 判断条件生效: 当前是web应用 才生效
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    // 判断条件生效: 有指定的类 才生效
    @ConditionalOnClass(CharacterEncodingFilter.class)
    // 判断条件生效: 指定的属性是指定值 才生效
    @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
    

理解

  1. SpringBoot启动会加载大量的自动配置类AutoConfigutaion

个人理解

  • 配置文件通过@ConfigurationProperties和大量xxxProperties类绑定
  • xxxProperties类会被@EnableConfigurationProperties(xxxProperties.class)导入yyyAutoConfiguration类中使用
  • yyyAutoConfiguration又是@ConditionalOnzzz条件性地生效的
  • 条件就是我们需要用啥, 就创造啥环境

1.4 快速创建项目

Spring Initializer

reources文件夹

结构

  • static 保存所有静态资源 js css images
  • templates 保存所有模板页面, 默认jar包, 使用嵌入式tomcat, 默认不支持jsp. 但可以使用模板引擎
  • application.properties Spring Boot应用配置文件

1.5 单元测试

@RunWith(StringRunner.class) - 用专门的驱动器

@SpringBootTest - 标识

可以在试期间很方便地使用一种类似于编码一样的方式进行自动注入

1.6 添加组件

(2.2中有详解)

2 Configuration

配置文件

  • application.properties
  • application.yaml

命名:

  • **必须是application.xxx: **名字不能变, 拓展名可以变

作用:

  • 修改底层自动帮我们配置好的默认值

2.0 配置文件加载

位置

By default, the configured locations are…The resulting search order is the following:

官网规定4个位置, 优先级按顺序

  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/

补充:

  • file: 是项目根目录
  • classpath: 是 resources根目录 | class根目录 (class这个我也不太确定)

互补加载

有冲突时按优先级, 没有冲突就都拿来

甚至还可以手动指定配置文件位置

项目打包以后, 我们可以使用命令行参数的形式来指定文件新位置. 指定的配置文件和默认加载的会共同作用, 也会形成互补记载作用

外部配置加载顺序

SpringBoot也可以从以下位置加载配置, 优先级从高到低:

  1. 命令行参数
  2. 来自java:comp/env的JNDI属性
  3. Java系统属性 (System.getProperties()) (jvm)
  4. OS环境变量
  5. RandomValuePropertySource配置的random.*属性值
  6. jar包外部的application-{profile}.properties或yml(带spring.profile)配置文件
  7. jar包内部的…
  8. jar包外部的application.properties或yml, (不带spring.profile)配置文件
  9. jar包内部的…
  10. @Configuration注解类上的@PropertySource
  11. 通过SpringApplication.setDefaultProperties指定的默认属性

6~9小结:

  • 优先加载带profile的
  • 外大于内

2.1 YAML

YAML Ain’t Markup Lauguage

以数据为中心, 与XML相比

基本语法

key:[空格]value

字符默认不加任何引号

  • 双引号, 不会转移字符串内的特殊字符, 特殊字符的特殊功能还在
    • "zhangsan \n lisi" --> zhangsan 换行 lisi
  • 单引号, 会转义特殊字符, 失去特殊功能
    • ‘zhangsan \n lisi’ -->'zhangsan \n lisi'

对象、Map

行内写法

person: {name: 张三, age: 18, id: 1001}

数组 List Set

核心符号: -

pets:
  - dog
  - cat
  - bird

# 行内写法
pets2: [cat, dog, bird]

2.2 获取配置文件中的值

从YAML

(顺序不重要, 只要都存在即可)

  1. JavaBean, Person.java中

    @Component
    @ConfigurationProperties(prefix = "person")
    @Validated	// 数据校验
    public class Person{
        private String name;
        private Integer age;
        private Map map;	// map
        private List list;	// list
        private Dog dog;	// 引用
        
        @Email(message="邮箱格式错误")
        private String email;
    }
    
    class Dog{
        private String name;
        private Integer age;
    }
    
    • @ConfigurationProperties - 告诉Boot将本类中的所有属性和配置文件中相关的配置进行绑定

    • (prefix = "person") - 从配置文件中person属性之下进行映射

  2. application.yaml

    person:
      name: zhangsan
      age: 3
      map: {key1: value1, key2: value2}
      list: 
        - code
    	- girl
        - basketball
      dog: 
    	name: wangcai
    	age: 3
    
  3. 单元测试

    @Autowired
    
    

说明:

  • 使用@ConfigurationProperties(prefix="person")和yaml中的该根元素绑定
  • @Validated + @Email 可以校验数据

注意:

  • 使用这个注解IDE可能会报红色警报, 是正常现象, 不一定影响使用.

从properties

也可以实现从中取值, 只是需要考虑乱码问题

乱码问题

properties会出现这个问题, 改编码就可以

还有一种方法: @Value + @PropertySource(…)

  1. 早期是从xml中的获取value属性的值

  2. 现在可以使用**@PropertySource(..) + @Value**来做同样的事情

还支持SpEL, 但不支持别的很多特性

  • 由于XML中标签支持SpEL表达式, 所以也支持!
@Component
// 绑定指定file
@PropertySource(value = "classpath:theOtherName.properties")
public class Person{
    @Value("${name}")
	private String name;
}

表达式

  • 这样还支持一种在配置文件中使用表达式的功能

    person:
    name: zhangsan
    id: ${random.int}
    id2: ${random.uuid} 
    

两种方式对比

功能 @ConfigurationProperties @Value
属性批量注入 × (需要每个设置@Value)
松散语法绑定 ×
SpEL ×
JSR303数据校验 ×
复杂类型封装 ×
配置文件位置 只能从全局配置文件中获取 可更精确指定位置
多文档块 ×
  • SpEL: id: ${random.int}, 继承自XML的优良传统
  • 松散语法绑定: last-name <> lastName
  • JSR303数据校验: @Validated + @Email

选择

  • 如果只是在某个业务逻辑中, 只是为了获取一次配置文件中某个值, 及用@Value
  • 如果专门编写了一个JavaBean和配置文件映射, 直接使用@ConfigurationProperties

向SpringBoot程序中添加组件

  • 之前可以用@ImportResource作为配置文件的导入方式

  • 它可以把指定文件导入Spring容器

对比

  • @PropertySource - 加载指定配置文件
  • @ImporResource - 向Spring容器中导入指定文件作为的配置文件

手写配置文件导入容器作正规配置文件, 在主启动类中

@ImportResource(location = {"classpath:beans.xml"})
// 下边是主启动类

但SpringBoot推荐

@Configuration + @Bean 全注解方式

@Configuration
public class MyAppConfig {
    /*
    方法名 组件id
    返回值 组件class
     */
    @Bean
    public HelloService helloService(){
        System.out.println("配置类@bean给容器中添加组件");
        return new HelloService();
    }
}
class HelloService{}

其他补充

配置文件处理器 (configuration-processor)

配置文件自动提示

官方建议, 导入这个依赖写配置会自动和JavaBean绑定, 会有自动提示

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-configuration-processorartifactId>
    <optional>trueoptional>
dependency>

JSR303数据校验

  • @Validated + @Email\或别的

  • @ConfigurationProperties才支持

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2nEhh9N3-1587907368473)(SpringBoot.assets/image-20200424213231750.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SwEjcf5V-1587907368474)(SpringBoot.assets/image-20200424213301075.png)]

  • @Null 验证是否为null
  • @NotNull 验证是否不为null, 不能检查空串""
  • @NotBlank 验证字符串是不是Null, 还有被Trim的长度是否大于0, 只对字符串, 且会去掉前后空格
  • @NotEmpty 验证是否为null, 或者empty
  • @AssertTrue 验证是否为true
  • @AssertFalse 验证是否为false
  • @Size(min=, max=) 验证Array\Collection\Map\String等长度是否在给定范围内
  • @Length(min=, max=) Validates that the annotated String is between min and max included
  • @Past 验证Date和Calender对象是否在当前系统时间之前
  • @Future 验证是否在系统之未来
  • @Pattern 验证String对象是否符合正则规则

2.3 配置文件占位符

分类

  • 随机数

    ${random.value}
    ${random.int} \ ${random.int(10)} \ ${random.int(1024,65536)}
    ${random.long}
    
  • 占位符, 获取之前的值

    app.name=APPNAME
    app.description=${app.name} is a 666 application
    app.description2=${app.lastname:hello} # 如果获取不到也可以走默认值hello
    

适用

properties | yaml 都支持

2.4 Profile

是Spring对不同运行环境提供不同配置支持的功能, 可以通过激活指定参数等方式快速切换环境

1 多Profile文件

先注意命名:

  • 规定必须以application开头, 比如:
    • application-test.properties
    • application-dev.properties

再选则:application.properties

# 1. 如果不设置, 默认找application.properties
# 2. 设置
spring.profiles.active=dev
# or
spring.profiles.active=test

2 YAML 多文档块

application.yml同一个文件中即可配置:

server:
  port: 8081
#选择激活方案 如果不选择激活, 则81
spring:
  profiles:
    active: dev

#方案
---
server:
  port: 8082
spring:
  profiles: dev
  
#方案
---
server:
  port: 8083
spring:
  profiles: test

激活指定profile的方式

  • 配置文件中激活

    (如上所述)

  • 命令行激活

    运行之前选择Edit Configurations... --> Program arguments: --> 以下命令

    --spring.profiles.active=dev
    

    或者在cmd命令行中运行时候再指定以上命令

    java -jar 项目包名 --spring.profiles.active=dev
    
  • JVM参数参数

    还在运行之前选择Edit Configurations... --> VM options – 输入以下

    -Dspring.profiles.active=dev
    

2.5 自动配置-原理2

配置文件到底能写什么, 记不住, 但如果懂原理, 会好很多

  1. SpringBoot启动时, 加载主配置\启动类, 开启了自动配置功能 @EnableAutoConfiguration

  2. @EnableAutoConfiguration作用:

    • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件

    • 在其父类AutoConfigurationImportSelector查看selectImports()方法的内容

    • 其中有个方法名为"获取候选配置们"的, 会返回一个configurationrations的候选配置对象,如下

      List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
      

      本来是个List, 但在被外围总方法返回出去之前转换成数组array

      它的底层是SpringFactoriesLoader.loadFactoryNames()

      作用是扫描所有jar包类路径下的META-INF/Spring.factories

      把扫描到的这些文件的内容包装成properties对象, 从properties中又获取EnableAutoConfiguration.class类 (类名)对应的值, 然后加载到容器中

  3. 将类路径下 META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到容器中, 每一个这样的xxxAutoConfiguration都是容器中的一个组件, 都加入到容器中. 这是"源", 只有他们都加入容器, boot才能正常启动

    # "源"
    # 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.cloud.CloudAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
    org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
    org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
    org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
    org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
    org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
    org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
    org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
    org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
    org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
    org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
    org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
    org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
    org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
    org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
    org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
    org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
    org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
    org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
    org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
    org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
    org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
    org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
    org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
    org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
    org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
    org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
    org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
    org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
    org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
    org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
    org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
    org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
    org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
    org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
    org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
    org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
    org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
    org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
    org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
    org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
    org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
    org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
    org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
    org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
    org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
    org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
    org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
    org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
    org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
    org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
    org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
    org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
    org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
    

举例理解

以HttpEncodingAutoConfiguration为例解释自动配置原理

@Configuration	// 标识是一个配置类, 以前编写的配置文件一样, 它也可以给容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class)	
// 上边注解: 启用指定类(HttpEncodingProperties.class)的@ConfigurationProperties功能: 和配置文件绑定功能
@ConditionalOnWebApplication	// Spring底层的@Conditionalxxx, 如果满足指定条件, 该配置类中的配置才会生效
// 上边这个注解作用: 判断是否为web应用
@ConditionalOnClass(CharacterEncodingFilter.class)
// 上注解作用: 判断当前项目是否存在指定的类, SpringMVC的编码过滤器
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
// 上注解作用: 判断配置文件中是否存在指定配置  matchIfMissing 如果不存在, 判断也成立
// 上注解作用2: 即使配置文件中不配置spring.http.encoding=enable, 也会默认生效
public class HttpEncodingAutoConfiguration {
    private final HttpEncodingProperties properties;

    // 只有一个有参构造, 则参数只能从容器中拿
	public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
		this.properties = properties;
	}

	@Bean	// 本类一旦生效, 这个bean成为一个组件加入容器
    // 这个组件的某些值需要从properties中获取值, 而这个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;
	}

	@Bean
	public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
		return new LocaleCharsetMappingsCustomizer(this.properties);
	}

	private static class LocaleCharsetMappingsCustomizer
			implements EmbeddedServletContainerCustomizer, Ordered {

		private final HttpEncodingProperties properties;

		LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
			this.properties = properties;
		}

		@Override
		public void customize(ConfigurableEmbeddedServletContainer container) {
			if (this.properties.getMapping() != null) {
				container.setLocaleCharsetMappings(this.properties.getMapping());
			}
		}

		@Override
		public int getOrder() {
			return 0;
		}

	}

}

这整个类的作用, 根据当前不同的条件, 决定此配置类是否生效! 都成立了, 就生效了!

一旦生效了然后呢? 这个自动配置类中的@Bean 会注入容器, 作为组件添加到容器中!

这个组件工作时需要从本类的properties中获取某些值, 而这个properties的属性都已经通过@ConfigurationProperties和配置文件映射了!厉害!

并且只有一个有参构造, 参数就是这个properties, 只能从容器中拿.

个人的理解, 也是给他人讲解时的白话:

  1. 主启动类的注解@SpringBootApplication封装了@EnableAutocofiguration, 其中又封装了selector选择器, 这个选择器会扫描/META-INF/propertiy.factories下的源, 就像整套整套的配置方案, 有个方法getCandidateConfigurations, 称他们为候选配置类.
  2. 这些候选配置类在启动时会在一系列@ConditionalXXX注解的仲裁下决定是否生效, 这些"条件性"则是根据我们在启动前做的准备工作来决定的, 啥也没准备有啥也没准备的条件, 配置有数据, 就根据配置有数据的条件, 仲裁决定具体的这个audoconfiguration要不要生效
  3. 一旦生效, 则这个自动配置类下的bean们会注入容器, 成为新的组件加入其中, 这些组件又从Properties获取属性.
  4. 而这些新的组件, 又已经通过properties对象以及@configurationProperties和配置文件绑定了! 这就决定了我们"能配置啥"

精髓

  • SpringBoot启动会加载大量的自动配置类
  • 我我们要看自己需要的功能有没有默认写好的自动配置类
  • 再看这个自动配置类中到底配置了那些组件, 只要存在我们需要的, 就不需要再手动来配置了, 没有再自己添加
  • 给容器中自动配置类添加组件时候, 会从properties类中获取某些属性, 这些属性又可以由我们在配置文件中赋值

重要组件

  • xxxAutoConfiguration: 自动配置类, 负责给容器中添加组件
  • xxxProperties: 封装配置文件中的相关属性

@Conditional…派生注解

底层

  • 底层封装OnXXClass的条件判断类
    • 封装match()方法, 判断条件匹配, 返回boolean

作用

@Conditional…指定的条件成立, 才给容器中添加组件.

比如

"条件性"地生效

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mbz6YuaJ-1587907368476)(SpringBoot.assets/image-20200425000946631.png)]

AutoConfiguration需要在一定条件下生效!

补充:

这个只作为理解的补充

放大HttpEncodingProperties.class

@ConfigurationProperties(prefix = "spring.http.encoding")	// 作用:从配置文件中获取指定的值, 以及同bean的属性绑定
public class HttpEncodingProperties {
    //...
}

所有可以在配置文件中配置的属性都是在这种XXXProperties类中封装着! 配置文件可以配置什么, 就可以以此为参照!

配置过程的日志输出

可以看到具体哪些自动配置类生效, 哪些未生效

开启:

  • 配置文件中输入

    debug: true
    

日志有以下部分:

“AUTO-CONFIGURATION REPORT” 自动配置报告

  • Positive matches: 启用了的自动配置类
  • Negative matches: 未匹配成功, 未启用的自动配置类

你可能感兴趣的:(Java,-,框架)