2.2 Spring Boot的依赖和自动配置
在上节中已经介绍了如何搭建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注解那样,它允许读入配置文件的内容来自定义自动初始化所需的内容,下节将探讨这个问题。