8

上一篇我们看到,我们很轻松的完成了项目的构建,那么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。如图:

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

前面 4 个是注解的元数据信息, 我们主要看后面 3 个注解:

@SpringBootConfiguration 点击进去,我们发现使用的是 Spring 的 @Configuration

clipboard.png

所以,到这里我们就可以知道,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等,如图

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

我们继续更进,在添加后,发现txApplication已经注册到Spring中了。
所以,我们在写启动类的时候,我们需要放在项目的顶级包中,以便SpringBoot进行扫描。

@Import(AutoConfigurationImportSelector.class) 导入注解,从名称上来看,它导入了一个自动配置导入选择器, 我们点击进去

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

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

clipboard.png

就这样,@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方法:

clipboard.png

直觉告诉我们,我们肯定从run方法入手,如图:
clipboard.png

方法中,先创建了一个SpringApplication的实例,然后调用实例的run方法,我们先看看new实例的时候做了什么,点击进去查看,

clipboard.png

点击267行

clipboard.png

我们可以看到,其实他主要做了几个事情:
1、根据classpath里面是否存在某个特征类来判断是否应该创建一个为Web应用使用的ApplicationContext类型
2、在应用的classpath中查找并加载所有可用的ApplicationContextInitializer
3、在应用的classpath中查找并加载所有可用的ApplicationListener

然后执行run方法。 我们看run方法,跟踪后,我们可以看到run方法的内部实现。

clipboard.png

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


妞见妞爱
44 声望15 粉丝

时光,不会辜负每一个平静努力的人...