SpringBoot原理深入篇

8次阅读

共计 4379 个字符,预计需要花费 11 分钟才能阅读完成。

上一篇我们看到,我们很轻松的完成了项目的构建,那么 SpringBoot 是如何做到的呢,在使用的使用又有哪些通用配置和注意事项呢?
其实 SpringBoot 给我们做了大量的自动配置功能,我们只需要引入对应的启动器就可以直接使用,作为 SpringBoot 的使用者,一定要对其原理有一个大致的了解,避免遇到问题时无法跟踪。接下来我们来分析分析。
启动原理和执行原理分析
一、SpringBoot 的启动原理
我们打开 POM.XML,注意看下面两个依赖:
<!– Inherit defaults from Spring Boot –>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>

<!– Add typical dependencies for a web application –>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
我们第一步是继承了父项目:spring-boot-starter-parent,然后在添加 spring-boot-starter-web(WEB 启动器)的依赖,项目就会自动给我们导入关于 WEB 项目所需要的配置和 JAR。如图:

可能我们还有疑问,为什么一个 mian 方法就可以直接运行了,我们看看 main 方法类。

整个方法中,就注解 @SpringBootApplication 和 SpringApplication 是我们不认识的,也比较脸生,而且项目的启动也是从这里运行的,那么我们就来看看他们是个啥,我们先看直接,我们把鼠标移动到注解上面。

发现他是一个组合注解,里面很有很注解,我们来对每个注解来分析一下:

前面 4 个是注解的元数据信息,我们主要看后面 3 个注解:
@SpringBootConfiguration 点击进去,我们发现使用的是 Spring 的 @Configuration

所以,到这里我们就可以知道,SpringBoot 使用的是 @Configuration 的方式来配置 IOC 容器,@Configuration 就好比对应我们原来的一个 XML 配置文件(SpringBoot 社区推荐使用基于 JavaConfig 的配置形式),比如:
我们原来是这么写:
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:mvc=”http://www.springframework.org/schema/mvc” xmlns:context=”http://www.springframework.org/schema/context”
xmlns:aop=”http://www.springframework.org/schema/aop” xmlns:tx=”http://www.springframework.org/schema/tx”
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd “>

<!– spring 配置 duid 数据库连接池的数据源 by 杨攀 –>
<bean id=”dataSource” class=”com.alibaba.druid.pool.DruidDataSource” init-method=”init” destroy-method=”close”>
….. 省略
</bean>

</beans>
而现在可以用 JavaConfig 这么配置:
/**
*@Description: 阿里连接池
*@Author: 杨攀
*@Since:2019 年 1 月 6 日下午 5:18:02
*/
@Configuration
public class DruidDataSourceConfig {

@Bean
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
// 设置参数
//….. 省略
return dataSource;
}
在该类中标注了 @Bean 的方法返回的实例,都会注入到 IOC 容器中,而 bean 的 id 默认为方法名。(注意:@Configuration 是 spring 的注解,不是 springboot 的,本身 spring 提供了 JavaConfig 的配置)。
@EnableAutoConfiguration 注解,如果熟悉 Spring 框架的人都知道,Spring 中也定义了很多 @Enable 开头的注解,比如:@EnableCaching 等,如图

他们都是通过 @import 来导入对应的配置类。SpringBoot 也是一样,@EnableAutoConfiguration 点击进入,也是通过 @import 来导入的。将所有符合自动配置条件的 bean 定义加载到 IOC 容器中

其中:@AutoConfigurationPackage 自动配置包注解,点击进去后,我们可以看到源代码:

其实这里就是把 bean 注册到 spring 中,我们可以断点看看

上图中,我们已经看到扫描到的包是 com.topinfo.yangp,就是我们 main 方法类的包及子包都会被扫描并注册。

我们继续更进,在添加后,发现 txApplication 已经注册到 Spring 中了。所以,我们在写启动类的时候,我们需要放在项目的顶级包中,以便 SpringBoot 进行扫描。
@Import(AutoConfigurationImportSelector.class) 导入注解,从名称上来看,它导入了一个自动配置导入选择器,我们点击进去

它实现了多个接口,并实现了一个 selectImports

然后我们点击 100 行,继续跟进去

我们看 199 行,getCandidateConfigurations 根据获取配置,点击

会去读取一个 spring.factories 的文件,读取不到会表这个错误,我们继续根据会看到,最终路径的长这样,而这个是 spring 提供的一个工具类。

它其实是去加载一个外部的文件,而这文件是在

我们打开这个文件,发现其有很多很多的自动配置类,包括 SpringMVC,这就是为什么我们一开始就可以直接使用 mvc 的原因,如图:

就这样,@EnableAutoConfiguration 就是从 classpath 中搜寻 META-INF/spring.factories 配置文件,并将其中 org.springframework.boot.autoconfigure.EnableutoConfiguration 对应的配置项通过反射(Java Refletion)实例化为对应的标注了 @Configuration 的 JavaConfig 形式的配置类,并加载到 IOC 容器中。
@ComponentScan 包扫描,就是根据定义的扫描路径, 把符合扫描规则的类装配到 spring 容器中
这样,关于 @SpringBootApplication 的注解的功能就分析差不多了,简单来说就是 3 个注解的组合注解,如:
@SpringBootApplication
|- @SpringBootConfiguration
|- @Configuration // 通过 javaConfig 的方式来添加组件到 IOC 容器中
|- @EnableAutoConfiguration
|- @AutoConfigurationPackage // 自动配置包,与 @ComponentScan 扫描到的添加到 IOC
|- @Import(AutoConfigurationImportSelector.class) // 到 META-INF/spring.factories 中定义的 bean 添加到 IOC 容器中
|- @ComponentScan 包扫描

关于 SpringBoot 的启动原理就差不多了。
二、SpringBoot 的执行原理
就是,嗯,注解我们刚刚看过了,我们现在来看看为什么 mian 方法执行后,项目就直接启动了,我们再来瞄一眼 main 方法:

直觉告诉我们,我们肯定从 run 方法入手,如图:
方法中,先创建了一个 SpringApplication 的实例,然后调用实例的 run 方法,我们先看看 new 实例的时候做了什么,点击进去查看,

点击 267 行

我们可以看到,其实他主要做了几个事情:1、根据 classpath 里面是否存在某个特征类来判断是否应该创建一个为 Web 应用使用的 ApplicationContext 类型 2、在应用的 classpath 中查找并加载所有可用的 ApplicationContextInitializer3、在应用的 classpath 中查找并加载所有可用的 ApplicationListener
然后执行 run 方法。我们看 run 方法,跟踪后,我们可以看到 run 方法的内部实现。

到此,SpringBoot 的启动执行就差不多了,,后面我们在将下 SpringBoot 的常用配置

正文完
 0