在上节中已经介绍了如何搭建Spring Boot工程,下面需要讨论它为什么在很少的配置下就能够运行。

下面以最常用的Spring MVC为例进行说明。首先打开Maven的本地仓库,找到对应Spring Boot的文件夹,可以看到图2-10所示的目录。

图2-10 Spring Boot的Maven本地仓库

这里先谈spring-boot-start-web的内容,未来还会谈到spring-boot-autoconfigure文件夹的内容,所以图 2-10 中一并加了框。打开spring-boot-start-web文件夹,就可以看到一个名为spring-boot- starter-web-2.0.0.RELEASE.pom的文件,打开它就可以看到代码清单2-2所示的代码。

代码清单2-2 spring-boot-starter-web的pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starters</artifactId>
    <version>2.0.0.RELEASE</version>
  </parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <version>2.0.0.RELEASE</version>
  <name>Spring Boot Web Starter</name>
  <description>Starter for building web, including RESTful, applications using Spring
        MVC. Uses Tomcat as the default embedded container</description>
  <url>https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/
  spring-boot-starter-web</url>
  <organization>
    <name>Pivotal Software, Inc.</name>
    <url>https://spring.io</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
    </license>
  </licenses>
  <developers>
    <developer>
      <name>Pivotal</name>
      <email>info@pivotal.io</email>
      <organization>Pivotal Software, Inc.</organization>
      <organizationUrl>http://www.spring.io</organizationUrl>
    </developer>
  </developers>
  <scm>
<connection>scm:git:git://github.com/spring-projects/spring-boot.git/spring-boot-
starters/spring-boot-starter-web</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-boot.git/
spring-boot-starters/spring-boot-starter-web</developerConnection>
<url>http://github.com/spring-projects/spring-boot/spring-boot-starters/spring-boot-
starter-web</url>
  </scm>
  <issueManagement>
    <system>Github</system>
    <url>https://github.com/spring-projects/spring-boot/issues</url>
  </issueManagement>
  <dependencies>
    <!-- Spring Boot的依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.0.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <!-- JSON依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.0.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <!-- Tomcat依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.0.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <!-- Hibernate Validator依赖-->
    <dependency>
      <groupId>org.hibernate.validator</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.7.Final</version>
      <scope>compile</scope>
    </dependency>
    <!-- Spring Web依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.4.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <!-- Spring Web MVC依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.4.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

代码中的中文注释是我加入的。从这里可以看出,当加入spring-boot-starter-web后,它会通过Maven将对应的资源加载到我们的工程中,这样便能够形成依赖。但是这样还不足以运行Spring MVC项目,要运行它还需要对Spring MVC进行配置,让它能够生产Spring MVC所需的对象,才能启用Spring MVC,所以还需要进一步探讨。

为了探讨Spring MVC在Spring Boot自动配置的问题,首先在本地下载的Maven仓库的目录spring-boot-autoconfigure中找到spring-boot-autoconfigure-2.0.0.RELEASE-sources.jar的包。它是一个源码包,把它解压缩出来,打开它目录下的子目录org\springframework\boot\autoconfigure\web\servlet后,我们就可以看到许多配置类,如图2-11所示。

图2-11 Spring Boot的默认配置类

这里可以看到存在很多的类,其中加框的类DispatcherServletAutoConfiguration就是一个对DispatcherServlet进行自动配置的类。因为本书不是源码分析的书,所以不对注解这些内容进行深入的探讨,只是截取DispatcherServletAutoConfiguration源码中的一个内部类DispatcherServletConfiguration对Spring Boot的自动配置做最基本的讲解,如代码清单2-3所示。

代码清单2-3 DispatcherServletAutoConfiguration部分源码分析

// 配置文件
@Configuration
// 配置条件满足类DefaultDispatcherServletCondition的验证
@Conditional(DefaultDispatcherServletCondition.class)
// 如果存在ServletRegistration类则进行配置
@ConditionalOnClass(ServletRegistration.class)
// 如果存在对应的属性配置(Spring MVC的是spring.mvc.*)则启用配置
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {

    private final WebMvcProperties webMvcProperties;

    public DispatcherServletConfiguration(WebMvcProperties webMvcProperties) {
        this.webMvcProperties = webMvcProperties;
    }

    @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet() {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.setDispatchOptionsRequest(
                this.webMvcProperties.isDispatchOptionsRequest());
        dispatcherServlet.setDispatchTraceRequest(
                this.webMvcProperties.isDispatchTraceRequest());
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(
                this.webMvcProperties.isThrowExceptionIfNoHandlerFound());
        return dispatcherServlet;
    }

    @Bean
    // 如果存在类定义则配置
    @ConditionalOnBean(MultipartResolver.class)
    // 判断如果不存在bean名称为DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME,则配置Bean
    @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
    public MultipartResolver multipartResolver(MultipartResolver resolver) {
        // Detect if the user has created a MultipartResolver but named it incorrectly
        return resolver;
    }

}

注意上述代码中加粗注解的注释,这些中文注释是我加入的,为的是更好地说明Spring Boot的自动配置功能。通过上面的代码,可以看到Spring Boot内部已经自动为我们做了很多关于DispatcherServlet的配置,其中的@EnableConfigurationProperties还能够在读取配置内容的情况下自动生成Spring MVC所需的类,有关这些内容的讨论可以参考附录。到这里,应该明白为什么几乎在没有任何配置下就能用Spring Boot启动Spring MVC项目,这些都是Spring Boot通过Maven依赖找到对应的jar包和嵌入的服务器,然后使用默认自动配置类来创建默认的开发环境。但是有时候,我们需要对这些默认的环境进行修改以适应个性化的要求,这些在Spring Boot中也是非常简单的,正如@EnableConfigurationProperties注解那样,它允许读入配置文件的内容来自定义自动初始化所需的内容,下节将探讨这个问题。