1.1 什么是Spring

我知道你现在可能迫不及待地想要开始编写Spring应用了,我可以向你保证,在本章结束之前,你肯定能够开发一个简单的Spring应用。首先,我将使用Spring的一些基础概念为你搭建一个舞台,帮助你理解Spring是如何运行起来的。

我知道你现在可能迫不及待地想要开始编写Spring应用了,我可以向你保证,在本章结束之前,你肯定能够开发一个简单的Spring应用。首先,我将使用Spring的一些基础概念为你搭建一个舞台,帮助你理解Spring是如何运行起来的。

我知道你现在可能迫不及待地想要开始编写Spring应用了,我可以向你保证,在本章结束之前,你肯定能够开发一个简单的Spring应用。首先,我将使用Spring的一些基础概念为你搭建一个舞台,帮助你理解Spring是如何运行起来的。

我知道你现在可能迫不及待地想要开始编写Spring应用了,我可以向你保证,在本章结束之前,你肯定能够开发一个简单的Spring应用。首先,我将使用Spring的一些基础概念为你搭建一个舞台,帮助你理解Spring是如何运行起来的。

举例来说,假设在应用的众多组件中,有两个是我们需要处理的:库存服务(用来获取库存水平)和商品服务(用来提供基本的商品信息)。商品服务需要依赖于库存服务,这样它才能提供商品的完整信息。图1.1阐述这些bean和Spring应用上下文之间的关系。
epub_29101559_7

图1.1 应用组件通过Spring的应用上下文来进行管理并实现互相注入

在核心容器之上,Spring及其一系列的相关库提供了Web框架、各种持久化可选方案、安全框架、与其他系统集成、运行时监控、微服务支持、反应式编程以及众多现代应用开发所需的特性。

在历史上,指导Spring应用上下文将bean装配在一起的方式是使用一个或多个XML文件(描述各个组件以及它们与其他组件的关联关系)。例如,如下的XML描述了两个bean,也就是InventoryService bean和ProductService bean,并且通过构造器参数将InventoryService装配到了ProductService中:

1
2
3
4
5
6
<bean id="inventoryService"
class="com.example.InventoryService" />
<bean id="productService"
class="com.example.ProductService" />
<constructor-arg ref="inventoryService" />
</bean>

但是,在最近的Spring版本中,基于Java的配置更为常见。如下基于Java的配置类是与XML配置等价的:

1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class ServiceConfiguration {
@Bean
public InventoryService inventoryService() {
return new InventoryService();
}
@Bean
public ProductService productService() {
return new ProductService(inventoryService());
}
}

@Configuration注解会告知Spring这是一个配置类,会为Spring应用上下文提供bean。这个配置类的方法使用@Bean注解进行了标注,表明这些方法所返回的对象会以bean的形式添加到Spring的应用上下文中(默认情况下,这些bean所对应的bean ID与定义它们的方法名称是相同的)。

相对于基于XML的配置方式,基于Java的配置会带来多项额外的收益,包括更强的类型安全性以及更好的重构能力。即便如此,不管是使用Java还是使用XML的显式配置,只有当Spring不能进行自动配置的时候才是必要的。

在Spring技术中,自动配置起源于所谓的自动装配(autowiring)和组件扫描(component scanning)。借助组件扫描技术,Spring能够自动发现应用类路径下的组件,并将它们创建成Spring应用上下文中的bean。借助自动装配技术,Spring能够自动为组件注入它们所依赖的其他bean。

最近,随着Spring Boot的引入,自动配置的能力已经远远超出了组件扫描和自动装配。Spring Boot是Spring框架的扩展,提供了很多增强生产效率的方法。最为大家所熟知的增强方法就是自动配置(autoconfiguration),Spring Boot能够基于类路径中的条目、环境变量和其他因素合理猜测需要配置的组件并将它们装配在一起。

我非常愿意为你展现一些关于自动配置的示例代码,但是我做不到。自动配置就像风一样,你可以看到它的效果,但是我找不到代码指给你说,“看!这就是自动配置的样例!”事情发生了,组件启用了,功能也提供了,但是不用编写任何代码。没有代码就是自动装配的本质,也是它如此美妙的原因所在。

Spring Boot大幅度减少了构建应用所需的显式配置的数量(不管是XML配置还是Java配置)。实际上,当完成本章的样例时,我们会有一个可运行的Spring应用,该应用只有一行Spring配置代码。

Spring Boot极大地改善了Spring的开发,因此很难想象在没有它的情况下如何开发Spring应用。因此,本书会将Spring和Spring Boot当成一回事。我们会尽可能多地使用SpringBoot,只有在必要的时候才使用显式配置。因为Spring XML配置是一种过时的方式,所以我们主要关注Spring基于Java的配置。

Spring Boot极大地改善了Spring的开发,因此很难想象在没有它的情况下如何开发Spring应用。因此,本书会将Spring和Spring Boot当成一回事。我们会尽可能多地使用SpringBoot,只有在必要的时候才使用显式配置。因为Spring XML配置是一种过时的方式,所以我们主要关注Spring基于Java的配置。

第1部分 Spring基础

本书的第1部分将会介绍如何开始编写Spring应用,并在这个过程中学习Spring的基础知识。

在第1章中,我将简要介绍Spring和Spring Boot的核心知识,并展示在构建第一个Spring应用Taco Cloud的过程中如何初始化Spring项目。在第2章中,我们将深入研究Spring MVC,了解如何在浏览器中显示模型数据,以及如何处理和验证表单输入。我们还会介绍选择视图模板库的技巧。在第3章中,我们将向Taco Cloud应用程序添加数据持久化功能。到时候,我们将介绍如何使用Spring的JDBC模板来插入数据,以及如何使用Spring Data声明JPA repository。第4章将介绍Spring应用程序的安全性,包括自动配置Spring安全性、声明自定义用户存储、自定义登录页面以及防止跨站请求伪造(CSRF)攻击。作为第1部分的结尾,我们将在第5章中学习配置属性。我们将了解如何细粒度调整自动配置bean、让应用组件使用配置属性,以及如何使用Spring profile。

关于本书

编写《Spring实战(第5版)》的目的是让读者学会使用Spring框架、Spring Boot以及Spring生态系统中各种辅助部分构建令人赞叹的应用程序。本书首先介绍如何使用Spring和Spring Boot开发基于Web、以数据库作为后端的Java应用;随后进行必要的扩展,展现如何与其他应用进行集成、使用反应式类型进行编程,以及将应用拆分为离散的微服务;最后讨论如何准备应用的部署。

尽管Spring生态系统中的每个项目都提供了完善的文档,但是本书所做的是所有参考文档都无法做到的事情:提供一个实用的、项目驱动的指南,将Spring的各种元素组合起来形成一个真正的应用。

谁应该阅读这本书

《Spring实战(第5版)》适用于刚刚开始学习Spring Boot和Spring框架的Java开发人员,也适用于想要超越基础知识并学习Spring新特性的经验丰富的Spring开发者。

这本书是如何组织的:路线图

本书分成了5个部分,共计19章。
第1部分涵盖构建Spring应用的基础话题。

  • 第1章介绍Spring和Spring Boot以及如何初始化Spring项目。在本章中,我们迈出构建Spring应用的第一步,在本书后续各章中,我们会对这个应用进行扩展。
  • 第2章讨论如何使用Spring MVC构建应用的Web层。在本章中,我们将会构建处理Web请求的控制器以及在浏览器中渲染信息的视图。
  • 第3章会深入探讨Spring应用的后端,在这里数据会持久化到关系型数据库中。
  • 在第4章中,我们会使用Spring Security认证用户并防止未认证的用户访问应用。
  • 第5章介绍如何使用Spring Boot的配置属性功能来配置Spring应用。我们还会学习如何使用profile选择性地应用配置。

第2部分讨论如何将Spring应用与其他应用进行集成。

  • 第6章延续第2章对Spring MVC的讨论,我们将会学习如何在Spring中编写REST API。
  • 第7章讨论了和第6章相对立的主题,展现Spring应用如何消费REST API。
  • 第8章会讨论如何使用异步通信技术让Spring应用发送和接收消息,这里会用到Java Message Service、RabbitMQ或Kafka。
  • 第9章讨论如何使用Spring Integration进行声明式的应用集成。

第3部分探讨Spring对反应式编程提供的全新支持。

  • 第10章介绍Reactor项目。这是一个反应式编程库,支撑了Spring 5的反应式特性。
  • 第11章重新探讨REST API开发,介绍全新的Web框架Spring WebFlux。该框架借用了很多Spring MVC的理念,但是为Web开发提供了新的反应式模型。
  • 第12章将会看一下如何使用Spring Data编写反应式数据持久化,我们将会读取和写入Cassandra与Mongo数据库。

第4部分将会拆分单体应用模型,介绍Spring Cloud和微服务开发。

  • 第13章会深入介绍服务发现,组合使用Spring和Netflix的注册中心实现Spring微服务的注册和发现。
  • 第14章将展现如何在配置服务器中实现中心化的应用配置,从而实现跨微服务共享配置。
  • 第15章会介绍Hystrix的断路器模式。它能够让微服务在面临失败时更有弹性。

在第5部分中,我们将会讨论如何做好将应用投入生产环境的准备,并看一下如何进行部署。

  • 第16章会介绍Spring Boot Actuator。它是Spring Boot的一个扩展,通过REST端点的形式暴露Spring应用内部的运行状况。
  • 第17章将会介绍如何使用Spring Boot Admin。它是构建在Actuator之上的一个用户友好的基于浏览器的管理应用。
  • 第18章将会讨论如何将Spring bean暴露为JMX MBean以及如何消费它们。
  • 在第19章中,我们会看到如何将Spring应用部署到各种生产环境中。

通常来讲,刚刚接触Spring的开发人员应该从第1章开始,并按顺序阅读每一章;经验丰富的Spring开发人员可能更愿意在任何感兴趣的时候参与进来。即便如此,每一章都是建立在前一章内容的基础上的,所以如果从中间开始阅读,那么可能会漏掉一些上下文信息。

关于代码

本书包含许多源代码的样例,有的是编号的程序清单,有的是普通文本内嵌的源码。在这两种情况下,源代码都使用固定宽度的字体排版,以便将其与普通文本分开。有时代码也会使用粗体显示,以便于强调此处代码与本章前面步骤的变更,比如为已有的代码行添加新的特性。

在许多情况下,原始源代码会重新格式化;我们添加了换行符和重新缩进,以适应书中可用的页面空间。在极少数情况下,这样做依然是不够的,在这种情况下程序清单会包括换行符(➥)。此外,当在文中描述代码的时候,源码中的注释通常会被移除。许多程序清单会有代码标注,用来突出强调重要的概念。

本书中样例的源码可以通过异步社区的本书页面下载。

其他在线资源

还需要其他帮助吗?

  • Spring的Web站点有很多有用的起步指南(其中一部分就是由本书的作者编写的)。
  • StackOverflow上的Spring标签和Spring Boot是一个询问Spring问题和帮助别人的好地方。帮助解决别人的Spring问题是学习Spring的好办法。

关于作者

克雷格·沃斯(Craig Walls)是Pivotal的首席工程师。他是Spring框架的热心推动者,经常在本地用户组和会议上发言,撰写关于Spring的文章。在不琢磨代码的时候,Craig正在计划去迪士尼世界或迪士尼乐园的下一次旅行,他希望尽可能多地陪伴他的妻子和两个女儿。

关于封面

《Spring实战(第5版)》的封面人物是“Le Caraco”,也就是约旦西南部卡拉克(Karak)省的居民。该省的首府是Al-Karak,那里的山顶有座城堡,对死海和周边的平原有着极佳的视野。这幅图出自1796年出版的法国旅游图书,Encyclopédiedes Voyages,由J.G.St.Sauveur编写。在那时,为了娱乐而去旅游还是相对新鲜的做法,而像这样的旅游指南是很流行的,它能够让旅行家和足不出户的人们了解法国其他地区和国外的居民。

Encyclopédiedes Voyages中多种多样的图画生动描绘了200年前世界上各个城镇和地区的独特魅力。在那时,相隔几十千米的两个地区着装就不相同,可以通过着装判断人们究竟属于哪个地区。这本旅行指南展现了那个时代和其他历史时代的隔离感和距离感,这与我们这个运动过度的时代是截然不同的。

从那以后,服装风格发生了改变,富有地方特色的多样性开始淡化。现在,有时很难说一个洲的居民和其他洲的居民有什么不同。可能,从积极的方面来看,我们用原来文化和视觉上的多样性换来了个人风格的多变性,或者可以说是更为多样化和有趣的知识科技生活。这本旅行指南中的图片反映了两个世纪前各个地区生活的多样性,我们现在用图书封面的方式对其进行了再现。Manning出版社的员工都认为这是计算机行业中一个很有意思的创意。

不知不觉间,已经参与了3个版本的《Spring实战》翻译。2007年春天,当时J2EE Without EJB的风潮刚刚兴起,还在读研的我在天津大学图书馆借到第1版的《Spring实战》,当时忙于毕业,没有把这本书完整地读完,但是依赖注入、面向切面编程等理念还是深深印在了脑海中,书中经典有趣的圆桌骑士样例更是驱使我读了很多相关的历史背景材料。

屈指算来,已经过去了10多年,Spring早已经成为企业级Java开发的事实标准,Spring Boot和Spring Cloud相关的技术引领潮流,更是成为Java工程师的必备技能。《Spring实战》的作者Craig Walls不断推陈出新,将这本经典图书更新到第5版。只是,10多年以前,我恐怕做梦也想不到会与这本书有这么深的缘分。

Spring之所以能够在技术不断更新换代的IT领域长盛不衰,并且引领技术架构发展的潮流,我想这是因为它一直没有偏离Rod Johnson最初的目标。那就是,根据技术的发展,不断优化和革新,让Java应用的开发更加便利和高效。从XML配置、注解配置,再到Spring Boot的自动化配置,Spring在不断简化,开发人员需要做的额外工作越来越少。虽然Rod Johnson早已离开Spring去开创新的事业了,但是我相信Spring的这种基因还是一直在的。在可以预见的未来,Spring及其家族产品依然是值得花时间投资学习的技术。

有时候,我也会思考,真正的技术到底是什么,是某一项生僻的配置还是某个新的API?我想,这都是技术,却不是最关键的。因为这些东西都是不稳定的、易变的,想要在新知识层出不穷的领域中不被淘汰,我们更应该去追求一些内在稳定不变的知识,比如技术规范、设计原理等。所以,希望本书的读者能够通过这本入门的读物,去更多地探究一些Spring底层的设计和实现原理。
本书第10章关于反应式编程的初稿由何品翻译,我负责统稿修改;另外,对于反应式编程的术语和规范,何品和他的团队都做了很多的工作,在此向他表示感谢。

再次感谢我的爱人和儿子,又容忍我把这几个月的业余时间都耗在了笔记本电脑的前面。

希望这本书对读者有所帮助,如果读者在阅读中遇到问题,可以通过levinzhang1981 @126.com或者微信levinzhang1981与我联系,祝阅读愉快。

张卫滨

2019年7月29日于大连

内容提要

本书是一本经典而实用的畅销Spring学习指南。

第5版涵盖了Spring 5.0和Spring Boot 2.0里程碑式的更新。全书分为5个部分,共19章。

  • 第1部分(第1~5章)涵盖了构建Spring应用的基础话题。
  • 第2部分(第6~9章)讨论如何将Spring应用与其他应用进行集成。
  • 第3部分(第10~12章)探讨Spring对反应式编程提供的全新支持。
  • 第4部分(第13~15章)拆分单体应用模型,介绍Spring Cloud和微服务开发。
  • 第5部分(第16~19章)讨论如何为应用投入生产环境做准备以及如何进行部署。

本书既适合刚开始学习Spring Boot和Spring框架的Java开发人员快速上手,也适合经验丰富的Spring开发人员学习Spring的新特性,尤其适用于企业级Java开发人员。

第38章 新模式

设计模式已经诞生多年,“23”这个数字也在逐渐变大,这是好事情,表明我们软件界正在积累、汇编我们的知识和经验。一个模式的提出和成熟需要一段时间,因此本章挑选了5 个大家时常使用,但又经常忽视的新模式进行讲解,即规格模式、对象池模式、雇工模式、 黑板模式、空对象模式。希望这5个新模式能够帮助大家解决更多的实际开发难题。

第33章 跨战区PK

创建类模式描述如何创建对象,行为类模式关注如何管理对象的行为,结构类模式则着重于如何建立一个软件结构,虽然三种模式的着重点不同,但是在实际应用中还是有重叠的,会出现一种模式适用、另外一种模式也适用的情况,我们到底该选用哪一个设计模式呢?本章就带领读者进入不同类设计模式PK的世界中,让你清晰地认识到各个模式的不同点以及它们的特长。

第32章 行为类模式大PK

行为类模式包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式。该组真可谓是人才济济,高手如云。行为类模式的11个模式基本上都是大家耳熟能详的,而且它们之间还有很多的相似点,特别是一些扩展部分就更加相似了,我们挑选几个比较重要的模式进行对比说明。

第30章 创建类模式大PK

创建类模式包括工厂方法模式、建造者模式、抽象工厂模式、单例模式和原型模式,它们都能够提供对象的创建和管理职责。其中的单例模式和原型模式非常容易理解,单例模式是要保持在内存中只有一个对象,原型模式是要求通过复制的方式产生一个新的对象,这两个不容易混淆。剩下的就是工厂方法模式、抽象工厂模式和建造者模式了,这三个之间有较多的相似性。

通过例子,我们可以看出代理模式和装饰模式有非常相似的地方,甚至代码实现都非常相似,特别是装饰模式中省略抽象装饰角色后,两者代码基本上相同,但是还是有细微的差别。

代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定:是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,它不对被主题角色(也就是被代理类)的功能做任何处理,保证原汁原味的调用。代理模式使用到极致开发就是AOP,这是各位采用Spring架构开发必然要使用到的技术,它就是使用了代理和反射的技术。

装饰模式是在要保证接口不变的情况下加强类的功能,它保证的是被修饰的对象功能比原始对象丰富(当然,也可以减弱),但不做准入条件判断和准入参数过滤,如是否可以执行类的功能,过滤输入参数是否合规等,这不是装饰模式关心的。

代理模式在Java的开发中俯拾皆是,是大家非常熟悉的模式,应用非常广泛,而装饰模式是一个比较拘谨的模式,在实际应用中接触比较少,但是也有不少框架项目使用了装饰模式,例如在JDK的java.io.*包中就大量使用装饰模式,类似如下的代码:

1
OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"))

这是装饰模式的一个典型应用,使用DataOutputStream封装了一个FileOutputStream,以方便进行输出流处理。

第31章 结构类模式大PK

结构类模式包括适配器模式、桥梁模式、组合模式、装饰模式、门面模式、享元模式和代理模式。为什么叫结构类模式呢?因为它们都是通过组合类或对象产生更大结构以适应更高层次的逻辑需求。我们来分析以下几个模式的相似点和不同点。