源码解析 (三) | Spring Boot

Scroll Down

前言

本人其实一直想学习spring boot源码,但是由于一直没时间去弄,弄了也没有专心学习完,所以这里就记录学习源码实现的笔记。

一、什么是springBoot

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。约定大于配置。Spring Boot应用中这些第三方库几乎可以是零配置的开箱即用(out-of-the-box),大部分的 Spring Boot 应用都只需要非常少量的配置代码(基于 Java 的配置),开发者能够更加专注于业务逻辑。

image.png

二、SpringBoot特点

  • 大量的starter框架组件开箱即用
  • 零xml配置
  • 内嵌Tomcat,无需外部容器War部署
  • 一站式开发、快速构建一个项目
  • 提供生产就绪型功能,如指标,健康检查和外部配置
  • 自动集成springMvc、spring框架

三、SpringBoot优点

  • 简化xml配置
  • 简化依赖
  • 简化部署
  • 简化监控
  • 丰富的其他工具组件生态圈

缺点:集成度较高,使用过程中不太容易了解底层。

四、SpringBoot核心理念

  • 快速整合第三方框架(Spring、Redis)
    (原理:Maven依赖整合和自定义starter)
  • 完全去除XML配置,采用注解形式
    (原理:顾名思义根据spring框架原生注解实现包装)
  • 无需外部容器,内嵌Tomcat容器
    (原理:Java语言创建Tomcat容器,将编译后class文件交给tomcat加载)

五、SpringBoot run方法源码解析

1)SpringBoot容器启动后其实会返回当前容器的上下文
2)SpringApplication.run(HelloApplication.class);等同于new SpringApplication(primarySources).run(args)

5.1、启动构造函数流程

new SpringApplication(primarySources).run(args)

  • 1、new SpringApplication()
  • 2、调用run方法

5.2、主要流程

image.png

  • webApplicationType类型解析表示判断项目是不是走响应式运行
// 判断项目中所有jar包中有没有reactive.DispatcherHandler和有没有servlet.DispatcherServlet
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
	return WebApplicationType.REACTIVE;
}
// 判断当前环境中有木有servlet.Servlet
for (String className : SERVLET_INDICATOR_CLASSES) {
	if (!ClassUtils.isPresent(className, null)) {
		return WebApplicationType.NONE;
	}
}
return WebApplicationType.SERVLET;
// 最后返回:WebApplicationType.SERVLET
  • WebApplicationType
NONE:不会嵌入web服务器,最终通过外部tomcat启动
SERVLET:需要servlet服务器运行
REACTIVE:使用响应式web启动
  • 获取当前项目需要加载的META-INF/spring.factories下的ApplicationContextInitializer和ApplicationListener
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  • 加载启动类到spring容器

六、@SpringBootApplication

6.1、@SpringBootConfiguration

  • @Configuration作用:将其类指定为启动类

6.2、@ComponentScan

扫描包下的类文件

6.3、@EnableAutoConfiguration

加载第三方配置类

image.png
该注解引入了AutoConfigurationImportSelector.class类,采用选择器方式,读取spring-boot-autocongigure包下面spring.factories,再找到EnableAutoConfiguration下面的109个配置类,再接着注册到IOC容器
image.png

注意这109个并不是全部注册进去,部分的包只有引入相关依赖才会注册进去

七、SpringBoot如何创建springMvc和tomcat

使用@EnableAutoConfiguration就会去加载下面两个配置类

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
  • DispatcherServletAutoConfiguration
    会加载ServletWebServerFactoryAutoConfiguration.class
    image.png
    该类表示支持tomcat、jetty、Undertow三种服务器
    这个时候就会设置tomcat端口、地址等默认信息
    先创建tomcat再去加载DispatcherServlet整个springMvc

八、总结启动流程

8.1、核心步骤

1、创建SpringApplication对象
2、调用run方法实现启动,并返回当前容器的上下文

8.2、详细流程

  • 1、创建SpringApplication对象,springboot容器初始化操作

  • 2、获取当前启动类型 原理:判断classpath是否有加载servlet返回spring web启动方式

  • 3、setInitializers读取spring boot包下面的spring.factories文件,获取对应的ApplicationContextInitializer装配到集合

  • 4、setListeners读取…下spring.factories文件,获取到ApplicationListener装配到集合

  • 5、mainApplicationClass获取当前运行的主函数

  • 6、调用run方法实现启动

  • 7、StopWatch stopWatch = new StopWatch(); 记录项目启动时间

  • 8、SpringApplicationRunListeners listeners = getRunListeners(args);
    读取META-INF/spring.factories文件SpringApplicationRunListener类型存入集合

  • 9、listeners.Starting() 循环调用监听starting 方法

  • 10、prepareEnvironment(listeners, applicationArguments);
    prepareEnvironment 读取配置文件到SpringBoot 容器

  • 11、Banner printedBanner = printBanner(environment);
    打印Banner日志

  • 12、context = createApplicationContext();
    创建SpringBoot上下文对象

  • 13、refreshContext(context); 刷新上下文

  • 14、创建tomcat容器

  • 15、加载SpringMvc

  • 16、afterRefresh定义一个空的模块给其他之类实现

  • 17、listeners.started 广播和回调机制通知监听器已经启动成功

  • 18、listeners.runing 广播和回调机制通知监听器启动成功runing