SpringBoot 原理分析(简单理解他的运行过程)

SpringBoot 原理

约定优于配置

> 实际应用中,我们90%以上的框架的项目配置都是差不多的,所以Spring团队,就弄出来了一个我们大家通用的配置,以后我们开发项目时就不需要再去配置这些繁琐的配置了

就比如:

当我们使用SSM框架,所有的maven依赖和版本都需要我们程序员自己去控制,去找寻相对应的依赖,并且如果依赖没有配合好,jar包冲突,还需要我们自己去解决,并且这个解决是非常耗时的

而springboot中 我们在创建Springboot项目后,即会在文件

spring-boot-starter-parent->spring-boot-dependencies中看到所有SpringBoot为我们创建好的约定配置

SpringBoot 原理分析(简单理解他的运行过程)_第1张图片

即:SpringBoot已经为我们配置好了大部分应用的版本配置等

那么,我们应该怎么去使用他呢?

全局配置的名称必须为application

开箱即用

SpringBoot 中的每一个Starter都是一个功能场景



    org.springframework.boot
    spring-boot-starter-web

比如我们在项目pom.xml中配置的依赖 spring-boot-starter-web

他的作用就是为我们启动spring中配置好的Web场景

Starter就是一个启动器

spring boot的依赖关系

我们新建一个项目:将项目的所有依赖全部删除,会发现我们在SpringBoot项目中的启动类不能使用了,我们需要给他添加下列一个核心依赖:

无法使用
SpringBoot 原理分析(简单理解他的运行过程)_第2张图片

为他添加一个核心依赖



    org.springframework.boot
    spring-boot-starter

SpringBoot 原理分析(简单理解他的运行过程)_第3张图片

添加此核心依赖后的核心jar包

添加此核心代码之后springboot启动类就能够启动了,但是因为没有添加spring的web依赖,他在启动之后就直接结束了。并不能通过他访问我们的8080接口

SpringBoot 原理分析(简单理解他的运行过程)_第4张图片

现在我们添加web启动器依赖

<!--web应用场景启动器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

在进行执行

SpringBoot 原理分析(简单理解他的运行过程)_第5张图片
他的服务器就启动成功了

因为springboot内置了tomcat,我们使用启动器后即可以直接使用他进行web访问

SpringBoot 原理分析(简单理解他的运行过程)_第6张图片

maven的标准的目录结构

目录结构介绍以及springboot配置文件

SpringBoot 原理分析(简单理解他的运行过程)_第7张图片

资源文件中多存放SpringBoot的配置文件 如:

application.properties的配置

或者是 application.yml的配置

在static和templates中可以存放我们需要的网页资源

SpringBoot 原理分析(简单理解他的运行过程)_第8张图片

这三种配置文件都能够配置springboot

三种文件配置优先级:

​ properties>yml>yaml

通常官方推荐使用yml

探索底层

注解

@SpringBootApplication

在启动类中找到@SpringBootApplication注解 并且ctrl+鼠标点击 进入注解中

SpringBoot 原理分析(简单理解他的运行过程)_第9张图片

发现除了注解的声明之外还有四个不同的注解

@SpringBootConfiguration

​ @Configuration

​ @Component

他的作用相当于我们在spring中的bean文件 自动创建我们需要的bean 并且交给springboot去维护管理

@EnableAutoConfiguration:这个注解 他所加载的组件,就是我们在pom中所声明的组件 以及SpringBoot默认给我们提供的组件 将组件实例化,交由我们的ioc容器去管理

​ @AutoConfigurationPackage

​ @Import({AutoConfigurationImportSelector.class})

@ComponentScan:扫描器 扫描我们写的一些组件,扫描的是启动类包下的所有组件

扫描的组件注解种类:@Server @Repository @Component

@Filter

**@EnableAutoConfiguration:**是我们的核心注解,开启自动配置/装配

@EnableAutoConfiguration:这个注解 他所加载的组件,就是我们在pom中所声明的组件 以及SpringBoot默认给我们提供的组件 将组件实例化,交由我们的ioc容器去管理

​	@AutoConfigurationPackage

​	@Import({AutoConfigurationImportSelector.class})
		核心中的核心

AutoConfigurationImportSelector.class类:

SpringBoot 原理分析(简单理解他的运行过程)_第10张图片
SpringBoot 原理分析(简单理解他的运行过程)_第11张图片

SpringBoot 原理分析(简单理解他的运行过程)_第12张图片

查看这个方法内的获取自动导入的方法

进入这个方法里面 打入一个断点,我们对他进行一下调试

SpringBoot 原理分析(简单理解他的运行过程)_第13张图片

SpringBoot 原理分析(简单理解他的运行过程)_第14张图片

筛选完成后,即只需要用到我们的23个包了

SpringBoot 原理分析(简单理解他的运行过程)_第15张图片

此时我们关闭调试,在pom中添加一个starter启动依赖

我们导入一个thymeleaf启动依赖

SpringBoot 原理分析(简单理解他的运行过程)_第16张图片

添加之后我们再次进行调试

SpringBoot 原理分析(简单理解他的运行过程)_第17张图片

到达过滤器,进行下一步

SpringBoot 原理分析(简单理解他的运行过程)_第18张图片

这时发现他已经变成了24个了

启动类>@SpringBootApplication>@EnableAutoConfiguration>@Import({AutoConfigurationImportSelector.class})>

public String[] selectImports(AnnotationMetadata annotationMetadata) > this.getAutoConfigurationEntry(annotationMetadata)>getCandidateConfigurations(annotationMetadata, attributes)>SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader())>return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList())

进入到一个加载Spring文件的工厂类

Enumeration urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");

他通过此行代码查找jar包中的资源位置 并对他们进行自动加载

我们去找到此行代码所说明的文件位置

找到spring-boot-autoconfiure–>在此包下找到他的地址META-INF/spring.factories

SpringBoot 原理分析(简单理解他的运行过程)_第19张图片

点击进入文件 发现他的配置文件中的

在这里插入图片描述

在这里插入图片描述

148-21 = 127 行

由此可以发现springboot的候选配置文件就是在这个文件中获取的

获取到了这127个文件后进入过滤器,根据pom导入的包和springboot自带包进行过滤后获取的就是我们启动此次服务器所需要的包了

SpringBoot 原理分析(简单理解他的运行过程)_第20张图片

他会在找到需要的包后

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

通过这两个注解自动导入我们的包

程序

SpringApplication

SpringBoot 原理分析(简单理解他的运行过程)_第21张图片

源码剖析

/**
 * Create a new {@link SpringApplication} instance. The application context will load
 * beans from the specified primary sources (see {@link SpringApplication class-level}
 * documentation for details. The instance can be customized before calling
 * {@link #run(String...)}.
 * @param resourceLoader the resource loader to use
 * @param primarySources the primary bean sources
 * @see #run(Class, String[])
 * @see #setSources(Set)
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	// 初始化资源加载器
	this.resourceLoader = resourceLoader;
	// 资源加载类不能为 null
	Assert.notNull(primarySources, "PrimarySources must not be null");
	// 初始化加载资源类集合并去重
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// 推断应用程序是不是web应用
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	// 设置初始化器(Initializer)
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	// 设置监听器 
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	// 推断出主应用入口类
	this.mainApplicationClass = deduceMainApplicationClass();
}
123456789101112131415161718192021222324252627

其中,在推断应用程序是不是web应用的时候调用了deduceFromClasspath() 方法

run方法

配置的归根结底都是通过类属性进行配置的

properties 所有的配置的底层都对应了一个类的属性

SpringBoot原理图

SpringBoot 原理分析(简单理解他的运行过程)_第22张图片

你可能感兴趣的:(SpringBoot)