文章目录
- Spring Boot 精要
- 1. 自动配置
- 2. 起步依赖
- 3. 命令行界面
- 4. Actuator
- 开发SpringBoot程序
- 1. 启动引导Spring
- 2. 测试Spring Boot应用程序
- 3. 配置应用程序属性
- 2.2 使用起步依赖
- 2.3 使用自动配置
- 专注于应用程序功能
Spring Boot 精要
Spring Boot将很多魔法带入了Spring应用程序的开发之中,其中最重要的是以下四个核心。
- 自动配置:针对很多Spring应用程序常见的应用功能,Spring Boot能自动提供相关配置。
- 起步依赖:告诉Spring Boot需要什么功能,它就能引入需要的库。
- 命令行界面:这是Spring Boot的可选特性,借此你只需写代码就能完成完整的应用程序,
无需传统项目构建。 - Actuator:让你能够深入运行中的Spring Boot应用程序
1. 自动配置
在任何Spring应用程序的源代码里,你都会找到Java配置或XML配置(抑或两者皆有),它们为应用程序开启了特定的特性和功能。举个例子,如果你写过用JDBC访问关系型数据库的应用程序,那你一定在Spring应用程序上下文里配置过 JdbcTemplate 这个Bean。那段配置看起来是这样的:
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
这段非常简单的Bean声明创建了一个 JdbcTemplate 的实例,注入了一个 DataSource 依赖。当然,这意味着你还需要配置一个 DataSource 的Bean,这样才能满足依赖。假设你将配置一个嵌入式H2数据库作为 DataSource Bean,完成这个配置场景的代码大概是这样的:
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScripts('schema.sql', 'data.sql')
.build();
}
这个Bean配置方法创建了一个嵌入式数据库,并指定在该数据库上执行两段SQL脚本。 build()方法返回了一个指向该数据库的引用。这两个Bean配置方法都不复杂,也不是很长,但它们只是典型Spring应用程序配置的一小部分。除此之外,还有无数Spring应用程序有着完全相同的方法。所有需要用到嵌入式数据库和JdbcTemplate 的应用程序都会用到那些方法。简而言之,这就是一个样板配置。
Spring Boot会为这些常见配置场景进行自动配置。如果Spring Boot在应用程序的Classpath里发现H2数据库的库,那么它就自动配置一个嵌入式H2数据库。如果在Classpath里发现JdbcTemplate ,那么它还会为你配置一个 JdbcTemplate 的Bean。你无需操心那些Bean的配置,Spring Boot会做好准备,随时都能将其注入到你的Bean里。Spring Boot的自动配置远不止嵌入式数据库和 JdbcTemplate ,它有大把的办法帮你减轻配置负担,这些自动配置涉及Java持久化API(Java Persistence API,JPA)、Thymeleaf模板、安全和Spring MVC。
2. 起步依赖
向项目中添加依赖是件富有挑战的事。你需要什么库?它的Group和Artifact是什么?你需要哪个版本?哪个版本不会和项目中的其他依赖发生冲突?
Spring Boot通过起步依赖为项目的依赖管理提供帮助。起步依赖其实就是特殊的Maven依赖和Gradle依赖,利用了传递依赖解析,把常用库聚合在一起,组成了几个为特定功能而定制的依赖。
举个例子,假设你正在用Spring MVC构造一个REST API,并将JSON(JavaScript Object Notation)作为资源表述。此外,你还想运用遵循JSR-303规范的声明式校验,并使用嵌入式的Tomcat服务器来提供服务。要实现以上目标,你在Maven或Gradle里至少需要以下8个依赖:
org.springframework:spring-core
org.springframework:spring-web
org.springframework:spring-webmvc
com.fasterxml.jackson.core:jackson-databind
org.hibernate:hibernate-validator
org.apache.tomcat.embed:tomcat-embed-core
org.apache.tomcat.embed:tomcat-embed-el
org.apache.tomcat.embed:tomcat-embed-logging-juli
如果打算利用Spring Boot的起步依赖,你只需添加Spring Boot的Web起步依赖( org.springframework.boot:spring-boot-starter-web ) ,仅此一个。它会根据依赖传递把其他所需依赖引入项目里,你都不用考虑它们。
比起减少依赖数量,起步依赖还引入了一些微妙的变化。向项目中添加了Web起步依赖,实际上指定了应用程序所需的一类功能。因为应用是个Web应用程序,所以加入了Web起步依赖。与之类似,如果应用程序要用到JPA持久化,那么就可以加入jpa起步依赖。如果需要安全功能,那就加入security起步依赖。简而言之,你不再需要考虑支持某种功能要用什么库了,引入相关起步依赖就行。
此外,Spring Boot的起步依赖还把你从“需要这些库的哪些版本”这个问题里解放了出来。起步依赖引入的库的版本都是经过测试的,因此你可以完全放心,它们之间不会出现不兼容的情况。
3. 命令行界面
除了自动配置和起步依赖,Spring Boot还提供了一种很有意思的新方法,可以快速开发Spring应用程序。Spring Boot CLI让只写代码即可实现应用程序成为可能。Spring Boot CLI利用了起步依赖和自动配置,让你专注于代码本身。CLI能检测到你使用了哪些类,它知道要向Classpath中添加哪些起步依赖才能让它运转起来。一旦那些依赖出现在Classpath中,一系列自动配置就会接踵而来,确保启用DispatcherServlet 和Spring MVC,这样控制器就能响应HTTP请求了。Spring Boot CLI是Spring Boot的非必要组成部分。虽然它为Spring带来了惊人的力量,大大简化了开发,但也引入了一套不太常规的开发模型。要是这种开发模型与你的口味相去甚远,那也没关系,抛开CLI,你还是可以利用Spring Boot提供的其他东西。
4. Actuator
Spring Boot的最后一块“拼图”是Actuator,其他几个部分旨在简化Spring开发,而Actuator则要提供在运行时检视应用程序内部情况的能力。安装了Actuator就能窥探应用程序的内部情况了,包括如下细节:
- Spring应用程序上下文里配置的Bean
- Spring Boot的自动配置做的决策
- 应用程序取到的环境变量、系统属性、配置属性和命令行参数
- 应用程序里线程的当前状态
- 应用程序最近处理过的HTTP请求的追踪情况
- 各种和内存用量、垃圾回收、Web请求以及数据源用量相关的指标
Actuator通过Web端点和shell界面向外界提供信息。如果要借助shell界面,你可以打开SSH(Secure Shell),登入运行中的应用程序,发送指令查看它的情况。
开发SpringBoot程序
项目创建完毕后,你应该能看到一个类似图下图的项目结构。
整个项目结构遵循传统Maven或Gradle项目的布局,即主要应用程序代码位于src/main/java目录里,资源都在src/main/resources目录里,测试代码则在src/test/java目录里。此刻还没有测试资源,但如果有的话,要放在src/test/resources里。
再进一步,你会看到项目里还有不少文件。
- build.gradle:Gradle构建说明文件。
- ReadingListApplication.java :应用程序的启动引导类(bootstrap class),也是主要的Spring配置类。
- application.properties :用于配置应用程序和Spring Boot的属性。
- ReadingListApplicationTests.java :一个基本的集成测试类。
因为构建说明文件里有很多Spring Boot的优点尚未揭秘,所以我打算把最好的留到最后,先让我们来看看 ReadingListApplication.java 。
1. 启动引导Spring
ReadingListApplication 在Spring Boot应用程序里有两个作用:配置和启动引导。首先,这是主要的Spring配置类。虽然Spring Boot的自动配置免除了很多Spring配置,但你还需要进行少量配置来启用自动配置。
ReadingListApplication 还是一个启动引导类。要运行Spring Boot应用程序有几种方式,其中包含传统的WAR文件部署。但这里的 main() 方法让你可以在命令行里把该应用程序当作一个可执行JAR文件来运行。这里向 SpringApplication.run() 传递了一个ReadingListApplication 类的引用,还有命令行参数,通过这些东西启动应用程序。
package readinglist;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ReadingListApplication {
public static void main(String[] args) {
SpringApplication.run(ReadingListApplication.class, args);
}
}
@SpringBootApplication 开启了Spring的组件扫描和Spring Boot的自动配置功能。实际上@SpringBootApplication 将三个有用的注解组合在了一起。
- Spring的 @Configuration :标明该类使用Spring基于Java的配置。虽然本书不会写太多配置,但我们会更倾向于使用基于Java而不是XML的配置。
- Spring的 @ComponentScan :启用组件扫描,这样你写的Web控制器类和其他组件才能被自动发现并注册为Spring应用程序上下文里的Bean。本章稍后会写一个简单的Spring MVC控制器,使用 @Controller 进行注解,这样组件扫描才能找到它。
- Spring Boot 的 @EnableAutoConfiguration : 这 个 不 起 眼 的 小 注 解 也 可 以 称 为@Abracadabra,就是这一行配置开启了Spring Boot自动配置的魔力,让你不用再写成篇的配置了。在Spring Boot的早期版本中,你需要在 ReadingListApplication 类上同时标上这三个注解,但从Spring Boot 1.2.0开始,有 @SpringBootApplication 就行了。
2. 测试Spring Boot应用程序
Initializr还提供了一个测试类的骨架,可以基于它为你的应用程序编写测试。但
ReadingListApplicationTests (代码清单2-2)不止是个用于测试的占位符,它还是一个例
子,告诉你如何为Spring Boot应用程序编写测试。
ackage readinglist;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import readinglist.ReadingListApplication;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(
classes = ReadingListApplication.class)
@WebAppConfiguration
public class ReadingListApplicationTests {
@Test
public void contextLoads() {
}
}
一个典型的Spring集成测试会用 @ContextConfiguration 注解标识如何加载Spring的应用程序上下文。但是,为了充分发挥Spring Boot的魔力,这里应该用 @SpringApplication-Configuration 注解。
ReadingListApplicationTests 里还有一个简单的测试方法,即 contextLoads() 。实际上它就是个空方法。但这个空方法足以证明应用程序上下文的加载没有问题。如果ReadingListApplication 里定义的配置是好的,就能通过测试。如果有问题,测试就会失败。
3. 配置应用程序属性
Initializr为你生成的application.properties文件是一个空文件。实际上,这个文件完全是可选的,你大可以删掉它,这不会对应用程序有任何影响,但留着也没什么问题。application.properties文件可以很方便地帮你细粒度地调整Spring Boot的自动配置。你还可以用它来指定应用程序代码所需的配置项.
server.port=8000
要注意的是,你完全不用告诉Spring Boot为你加载 application.properties ,只要它存在就会被加载,Spring和应用程序代码都能获取其中的属性。
2.2 使用起步依赖
Spring Boot通过提供众多起步依赖降低项目依赖的复杂度。起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。很多起步依赖的命名都暗示了它们提供的某种或某类功能。
举例来说,你打算把这个阅读列表应用程序做成一个Web应用程序。与其向项目的构建文件里添加一堆单独的库依赖,还不如声明这是一个Web应用程序来得简单。你只要添加Spring Boot的Web起步依赖就好了。
我们还想以Thymeleaf为Web视图,用JPA来实现数据持久化,因此在构建文件里还需要Thymeleaf和Spring Data JPA的起步依赖。为了能进行测试,我们还需要能在Spring Boot上下文里运行集成测试的库,因此要添加Spring Boot的test起步依赖,这是一个测试时依赖。统统放在一起,就有了这五个依赖,也就是Initializr在Gradle的构建文件里提供的:
dependencies {
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "com.h2database:h2"
testCompile("org.springframework.boot:spring-boot-starter-test")
}
正如先前所见,添加这些依赖的最简单方法就是在Initializr里选中Web、Thymeleaf和JPA复选框。但如果在初始化项目时没有这么做,当然也可以稍后再编辑生成的build.gradle或pom.xml。通过传递依赖,添加这四个依赖就等价于加了一大把独立的库。这些传递依赖涵盖了Spring MVC、Spring Data JPA、Thymeleaf等内容,它们声明的依赖也会被传递依赖进来。这四个起步依赖的具体程度恰到好处。我们并没有说想要Spring MVC,只是说想要构建一个Web应用程序。我们并没有指定JUnit或其他测试工具,只是说我们想要测试自己的代码。Thymeleaf和Spring Data JPA的起步依赖稍微具体一点,但这也只是由于没有更模糊的方法声明这种需要。我们并不需要指定版本号,起步依赖本身的版本是由正在使用的Spring Boot的版本来决定的,而起步依赖则会决定它们引入的传递依赖的版本。
如果你真想知道自己在用什么,在构建工具里总能找到你要的答案。在Gradle里,dependencies 任务会显示一个依赖树,其中包含了项目所用的每一个库以及它们的版本:
$ gradle dependencies
在Maven里使用 dependency 插件的 tree 目标也能获得相似的依赖树。
$ mvn dependency:tree
大部分情况下,你都无需关心每个Spring Boot起步依赖分别声明了些什么东西。Web起步依赖能让你构建Web应用程序,Thymeleaf起步依赖能让你用Thymeleaf模板,Spring Data JPA起步依赖能让你用Spring Data JPA将数据持久化到数据库里,通常只要知道这些就足够了。
2.3 使用自动配置
Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。
举几个例子,下面这些情况都是Spring Boot的自动配置要考虑的。
- Spring的 JdbcTemplate 是不是在Classpath里?如果是,并且有 DataSource 的Bean,则自动配置一个 JdbcTemplate 的Bean。
- Thymeleaf是不是在Classpath里?如果是,则配置Thymeleaf的模板解析器、视图解析器以及模板引擎。
- Spring Security是不是在Classpath里?如果是,则进行一个非常基本的Web安全设置。每当应用程序启动的时候,Spring Boot的自动配置都要做将近200个这样的决定,涵盖安全、集成、持久化、Web开发等诸多方面。所有这些自动配置就是为了尽量不让你自己写配置。
专注于应用程序功能
Spring Boot运用条件化配置的方法是,定义多个特殊的条件化注解,并将它们用到配置类上。表2-1列出了Spring Boot提供的条件化注解。
一般来说,无需查看Spring Boot自动配置类的源代码,但为了演示如何使用表2-1里的注解,我们可以看一下 DataSourceAutoConfiguration 里的这个片段(这是Spring Boot自动配置库的一部分):
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
...
}
DataSourceAutoConfiguration 添加了 @Configuration 注解,它从其他配置类里导入了一些额外配置,还自己定义了一些Bean。最重要的是, DataSourceAutoCon-figuration 上添加了 @ConditionalOnClass 注解,要求Classpath里必须要有 DataSource 和EmbeddedDatabaseType 。如果它们不存在,条件就不成立, DataSourceAutoConfiguration提供的配置都会被忽略掉。DataSourceAutoConfiguration 里嵌入了一个 JdbcTemplateConfiguration 类,自动配置了一个 JdbcTemplate Bean:
@Configuration
@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class)
protected static class JdbcTemplateConfiguration {
@Autowired(required = false)
private DataSource dataSource;
@Bean
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}
...
}
JdbcTemplateConfiguration 使用了 @Conditional 注解,判断 DataSourceAvailable-Condition 条件是否成立——基本上就是要有一个 DataSource Bean或者要自动配置创建一个。假 设 有 DataSource Bean , 使 用 了 @Bean 注 解 的 jdbcTemplate() 方 法 会 配 置 一 个JdbcTemplate Bean。这个方法上还加了@ConditionalOnMissingBean 注解,因此只有在不存在 JdbcOperations (即 JdbcTemplate 实现的接口)类型的Bean时,才会创建 JdbcTemplate Bean。
此处看到的只是 DataSourceAutoConfiguration 的冰山一角,Spring Boot提供的其他自动配置类也有很多知识没有提到。但这已经足以说明Spring Boot如何利用条件化配置实现自动配置。
自动配置会做出以下配置决策,它们和之前的例子息息相关。
- 因为Classpath里有H2,所以会创建一个嵌入式的H2数据库Bean,它的类型是javax.sql.DataSource ,JPA实现(Hibernate)需要它来访问数据库。
- 因为Classpath里有Hibernate(Spring Data JPA传递引入的)的实体管理器,所以自动配置会配置与 Hibernate相关的 Bean,包括 Spring的 LocalContainerEntityManager-FactoryBean 和 JpaVendorAdapter 。
- 因为Classpath里有Spring Data JPA,所以它会自动配置为根据仓库的接口创建仓库实现。
- 因为Classpath里有Thymeleaf,所以Thymeleaf会配置为Spring MVC的视图,包括一个Thymeleaf的模板解析器、模板引擎及视图解析器。视图解析器会解析相对于Classpath根目录的/templates目录里的模板。
- 因 为 Classpath 里 有 Spring MVC ( 归 功 于 Web 起 步 依 赖 ), 所 以 会 配 置 Spring 的DispatcherServlet 并启用Spring MVC。
- 因为这是一个Spring MVC Web应用程序,所以会注册一个资源处理器,把相对于Classpath根目录的/static目录里的静态内容提供出来。(这个资源处理器还能处理/public、/resources和/META-INF/resources的静态内容。)
- 因为Classpath里有Tomcat (通过Web起步依赖传递引用),所以会启动一个嵌入式的Tomcat容器,监听8080端口。
Spring Boot自动配置承担起了配置Spring的重任,因此你能专注于编写自己的应用程序。