2、SpringBoot:运行原理初探
我们之前写的 HelloSpringBoot,到底是怎么运行的呢,Maven 项目,我们一般从 pom.xml 文件探究起;
pom.xml
2.1、父依赖
其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件!
点进去,发现还有一个父依赖
这里才是真正管理 SpringBoot 应用里面所有依赖版本的地方,SpringBoot 的版本控制中心;
以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;
2.2、启动器 spring-boot-starter
springboot-boot-starter-xxx:就是 spring-boot 的场景启动器
spring-boot-starter-web:帮我们导入了 web 模块正常运行所依赖的组件;
SpringBoot 将所有的功能场景都抽取出来,做成一个个的 starter (启动器),只需要在项目中引入这些 starter 即可,所有相关的依赖都会导入进来 , 我们要用什么功能就导入什么样的场景启动器即可 ;我们未来也可以自己自定义 starter;
主启动类
分析完了 pom.xml 来看看这个启动类
2.3、默认的主启动类
但是一个简单的启动类并不简单!我们来分析一下这些注解都干了什么
2.4、@SpringBootApplication
作用:标注在某个类上说明这个类是 SpringBoot 的主配置类 , SpringBoot 就应该运行这个类的 main 方法来启动 SpringBoot 应用;
进入这个注解:可以看到上面还有很多其他注解!
2.5、@ComponentScan
这个注解在 Spring 中很重要 , 它对应 XML 配置中的元素。
作用:自动扫描并加载符合条件的组件或者 bean , 将这个 bean 定义加载到 IOC 容器中
2.6、@SpringBootConfiguration
作用:SpringBoot 的配置类 ,标注在某个类上 , 表示这是一个 SpringBoot 的配置类;
我们继续进去这个注解查看
这里的 @Configuration,说明这是一个配置类 ,配置类就是对应 Spring 的 xml 配置文件;
里面的 @Component 这就说明,启动类本身也是 Spring 中的一个组件而已,负责启动应用!
我们回到 SpringBootApplication 注解中继续看。
2.7、@EnableAutoConfiguration
@EnableAutoConfiguration :开启自动配置功能
以前我们需要自己配置的东西,而现在 SpringBoot 可以自动帮我们配置 ;@EnableAutoConfiguration 告诉 SpringBoot 开启自动配置功能,这样自动配置才能生效;
点进注解接续查看:
@AutoConfigurationPackage :自动配置包
@import :Spring 底层注解 @import , 给容器中导入一个组件
Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到 Spring 容器 ;
这个分析完了,退到上一步,继续看
@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ;
AutoConfigurationImportSelector :自动配置导入选择器,那么它会导入哪些组件的选择器呢?我们点击去这个类看源码:
1、这个类中有一个这样的方法
2、这个方法又调用了 SpringFactoriesLoader 类的静态方法!我们进入 SpringFactoriesLoader 类 loadFactoryNames() 方法
3、我们继续点击查看 loadSpringFactories 方法
4、发现一个多次出现的文件:spring.factories,全局搜索它
2.8、spring.factories
我们根据源头打开 spring.factories , 看到了很多自动配置的文件;这就是自动配置根源所在!
WebMvcAutoConfiguration
我们在上面的自动配置类随便找一个打开看看,比如 :WebMvcAutoConfiguration
可以看到这些一个个的都是 JavaConfig 配置类,而且都注入了一些 Bean,可以找一些自己认识的类,看着熟悉一下!
所以,自动配置真正实现是从 classpath 中搜寻所有的 META-INF/spring.factories 配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration 的 JavaConfig 形式的 IOC 容器配置类 , 然后将这些都汇总成为一个实例并加载到 IOC 容器中。
结论:
- SpringBoot 在启动的时候从类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值
- 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
- 整个 J2EE 的整体解决方案和自动配置都在 springboot-autoconfigure 的 jar 包中;
- 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;
- 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;
现在大家应该大概的了解了下,SpringBoot 的运行原理,后面我们还会深化一次!
SpringApplication
2.9、不简单的方法
我最初以为就是运行了一个 main 方法,没想到却开启了一个服务;
SpringApplication.run 分析
分析该方法主要分两部分,一部分是 SpringApplication 的实例化,二是 run 方法的执行;
2.10、SpringApplication
这个类主要做了以下四件事情:
1、推断应用的类型是普通的项目还是 Web 项目
2、查找并加载所有可用初始化器 , 设置到 initializers 属性中
3、找出所有的应用程序监听器,设置到 listeners 属性中
4、推断并设置 main 方法的定义类,找到运行的主类
查看构造器:
2.11、run 方法流程分析
3、SpringBoot:yaml 配置注入
yaml 语法学习
3.1、配置文件
SpringBoot 使用一个全局的配置文件 , 配置文件名称是固定的
-
application.properties
-
- 语法结构 :key=value
-
application.yml
-
- 语法结构 :key:空格 value
配置文件的作用 :修改 SpringBoot 自动配置的默认值,因为 SpringBoot 在底层都给我们自动配置好了;
比如我们可以在配置文件中修改 Tomcat 默认启动的端口号!测试一下!
3.2、yaml 概述
YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)
这种语言以数据作为中心,而不是以标记语言为重点!
以前的配置文件,大多数都是使用 xml 来配置;比如一个简单的端口配置,我们来对比下 yaml 和 xml
传统 xml 配置:
yaml 配置:
3.3、yaml 基础语法
说明:语法要求严格!
1、空格不能省略
2、以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
3、属性和值的大小写都是十分敏感的。
字面量:普通的值 [数字,布尔值,字符串]
字面量直接写在后面就可以 , 字符串默认不用加上双引号或者单引号;
注意:
-
“ ” 双引号,不会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;
比如 :name: "kuang shen" 输出 :kuang 换行 shen
-
'' 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出
比如 :name: ‘kuang shen’ 输出 :kuang shen
对象、Map(键值对)
在下一行来写对象的属性和值得关系,注意缩进;比如:
行内写法
数组( List、set )
用 - 值表示数组中的一个元素, 比如:
行内写法
修改 SpringBoot 的默认端口号
配置文件中添加,端口号的参数,就可以切换端口;
注入配置文件
yaml 文件更强大的地方在于,他可以给我们的实体类直接注入匹配值!
3.4、yaml 注入配置文件
1、在 springboot 项目中的 resources 目录下新建一个文件 application.yml
2、编写一个实体类 Dog;
3、思考,我们原来是如何给 bean 注入属性值的!@Value,给狗狗类测试一下:
4、在 SpringBoot 的测试类下注入狗狗输出一下;
结果成功输出,@Value 注入成功,这是我们原来的办法对吧。
5、我们在编写一个复杂一点的实体类:Person 类
6、我们来使用 yaml 配置的方式进行注入,大家写的时候注意区别和优势,我们编写一个 yaml 配置!
7、我们刚才已经把 person 这个对象的所有值都写好了,我们现在来注入到我们的类中!
8、IDEA 提示,springboot 配置注解处理器没有找到,让我们看文档,我们可以查看文档,找到一个依赖!
9、确认以上配置都 OK 之后,我们去测试类中测试一下:
结果:所有值全部注入成功!
yaml 配置注入到实体类完全 OK!
课堂测试:
1、将配置文件的 key 值 和 属性的值设置为不一样,则结果输出为 null,注入失败
2、在配置一个 person2,然后将 @ConfigurationProperties(prefix = "person2") 指向我们的 person2;
3.5、加载指定的配置文件
@PropertySource :加载指定的配置文件;
@configurationProperties:默认从全局配置文件中获取值;
1、我们去在 resources 目录下新建一个 person.properties 文件
2、然后在我们的代码中指定加载 person.properties 文件
3、再次输出测试一下:指定配置文件绑定成功!
3.6、配置文件占位符
配置文件还可以编写占位符生成随机数
3.7、回顾 properties 配置
我们上面采用的 yaml 方法都是最简单的方式,开发中最常用的;也是 springboot 所推荐的!那我们来唠唠其他的实现方式,道理都是相同的;写还是那样写;配置文件除了 yml 还有我们之前常用的 properties , 我们没有讲,我们来唠唠!
【注意】properties 配置文件在写中文的时候,会有乱码 , 我们需要去 IDEA 中设置编码格式为 UTF-8;
settings-->FileEncodings 中配置;
测试步骤:
1、新建一个实体类 User
2、编辑配置文件 user.properties
3、我们在 User 类上使用 @Value 来进行注入!
4、Springboot 测试
结果正常输出: