上一篇我们看到,我们很轻松的完成了项目的构建,那么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 */@Configurationpublic 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的常用配置