开发必会系列:《spring实战(第4版)》读书笔记
一 spring的核心
1、主要概念
DI能够让相互协作的软件组件保持松散耦合,而面向切面编程(AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。
spring有两类容器实现方式,bean工厂(BeanFactory)和应用上下文(ApplicationContext),bean工厂比较低级,主要用应用上下文。
应用上下文类,常见有以下几种:
AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文。
AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。
FileSystemXmlApplicationContext:从文件系统下的一个或多个XML配置文件中加载上下文定义。
spring应用上下文中所有的bean都会给定一个ID。
依赖注入(DI)的本质:创建应用对象之间协作关系的行为,也成为装配(wiring)。
2、装配bean
spring装配bean有三种方式,在xml中进行显式配置,在Java中进行显式配置,隐式的bean发现机制和自动装配。一般都用自动装配。spring从两个角度实现自动化装配:
组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean。
自动装配(auto wiring):spring自动满足bean之间的依赖。
这俩组合起来用。
@component注解表明该类会作为组件类,并告知spring要为这个类创建bean。组件扫描默认不启用,可以手动开启,但springboot里默认扫描入口类及其同级目录。
3、高级装配
要让bean根据不同环境生效,使用@profile("这里写dev或prod啥的")注解。
也可以在xml中,使用<beans profile="dev">这里写当前环境下的具体配置</beans>,由于每次启动只能加载一个bean,所以要激活profile,激活依赖于两个属性,在web.xml中,spring默认找spring.profiles.default的值,若同时存在spring.profiles.active的值则优先用这个。
条件化bean,使用@Conditional注解,用于在某种条件满足时,才创建这个bean。
装配歧义:多个类实现了一个接口,spring进行set时就没有唯一的可选值,会报错,此时可以用primary将一个bean设为首选,或使用限定符qualifier帮spring缩小范围到只有一个bean.
bean的作用域
spring默认bean为单例(singleton),不管给定的一个bean被注入到其他bean多少次,每次所注入的都是同一个实例。
单例可以保持一些状态,减轻垃圾回收成本。但若使用的类,是要让它变成很多个去用(mutable),那单例会使对象被污染。
单例:在整个应用中,之创建bean的一个实例。
原型(prototype):每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean实例。
会话(session):在web应用中,为每个会话创建一个bean实例。
请求(request):在web应用中,为每个请求创建一个bean实例。
举个例子,web应用中,一个电商网站,一个bean代表用户的购物车,如果是单例,所有用户向同一个购物车添加商品;如果是原型,这里添加的商品,那里看不见;如果是会话,就合适了。
运行时值注入:当我们希望避免硬编码值,而是想让这些值在运行时再确定,可以用spring提供的两种方式:属性占位符(property placeholder)、更强大的spring 表达式语言(SpEL)
4、面向切面
软件开发中,散布于应用中多处的功能被称为横切关注点(cross-cutting concern)。通常,这些横切关注点从概念上是与应用的业务逻辑相分离的(但是往往会直接嵌入到应用的业务逻辑之中)。把这些横切关注点与业务逻辑相分离正是面向切面编程(AOP)所要解决的问题。
应用切面主要用于日志、声明式事务、安全、缓存等方面。
描述切面的术语:
通知:定义了切面是什么以及何时使用。有5种:前置、后置、返回、异常、环绕。
连接点:啥时候用通知,比如调用方法时?抛出异常时?
切点:切点描述了切面在哪,有助于缩小切面所通知的连接点的范围。
切面:是通知和切点的结合,他俩共同定义了切面的全部内容——它是什么、在何时、何处完成其功能。
引入:允许我们向现有的类添加新方法或属性。
织入:把切面应用到目标对象并创建新的代理对象的过程。
spring对AOP的支持局限于方法拦截。AspectJ提供了spring AOP所不能支持的许多类型的切点。
二 web中的spring
以我目前的公司来说,随着企业业务规模扩大,微服务的普及,前后端分离已经是大势所趋,后端从以前的全能变得专注于接口,spring mvc在后面的章节讲了如何转REST,所以这节随便看看。
5、构建spring web应用程序
spring mvc允许客户端传输的数据类型:查询参数(Query Parameter)、表单参数(Form Parameter)、路径变量(Path Variable)
6、渲染web视图
7、spring mvc高级技术
8、spring web flow:
它是spring mvc的扩展,支持开发基于流程的应用程序。它将流程的定义与实现流程行为的类和视图分离开来。
当用户进入一个流程时,流程执行器会为用户创建并启动一个流程执行实例。
9、保护web应用:spring security用于过滤web请求、查询用户信息、拦截请求、认证用户、保护视图。
三 后端中的spring
spring对数据访问的支持,也贯彻了面向对象原则中的“针对接口编程”。
spring应用需要从某种类型的数据库中读取和写入数据。为了避免持久化的逻辑分散到应用的各个组件中,最好将数据访问的功能放到一个或多个专注于此项任务的组件中。这样的组件通常称为数据访问对象(data access object,DAO)或Repository。这样做的好处:
第一,它使得服务对象易于测试,因为它们不再与特定的数据访问实现绑定在一起。实际上,你可以为这些数据访问接口创建mock实现,这样无需连接数据库就能测试服务对象,而且会显著提升单元测试的效率并排除因数据不一致所造成的测试失败。
第二,数据访问层是以持久化技术无关的方式进行访问的。持久化方式的选择独立于Repository,同时只有数据访问相关的方法才通过接口进行暴露。这可以实现灵活的设计,并且切换持久化框架对应用程序其他部分所带来的影响最小。如果将数据访问层的实现细节渗透到应用程序的其他部分中,那么整个应用程序将数据访问层耦合在一起,从而导致僵化的设计。
配置数据源:websphere、JBoss、Tomcat这些服务器允许配置通过JNDI获取数据源,使数据源完全在应用程序之外进行管理。另外在应用服务器中管理的数据源通常以池的方式组织。如果不能从JNDI中查找数据源,也可以直接在spring中配置数据源连接池。
10、spring整合JDBC:JdbcTemplate
11、整合ORM框架:spring整合hibernate;Java持久化API(Java Persistence API,JPA)是基于POJO的持久化机制,它从hibernate和Java数据对象(Java Data Object,JDO)上借鉴了很多理念并加入了Java5注解的特性。
12、Nosql数据库:mongodb持久化文档数据;neo4j操作图数据;redis操作key-value数据
13、缓存数据:spring对缓存的支持有两种方式:注解驱动的缓存;xml声明的缓存。
14、保护方法:spring security提供了三种不同的安全注解:自带的@secured注解;JSR-250的@rolesAllowed注解;表达式驱动的注解,包括@PreAuthorize、@PostAuthorize、@PreFilter、@PostFilter。
四 spring集成
15、使用远程服务
现有的远程调用技术及适用场景:
远程方法调用(Remote Method Invocation,RMI):不考虑网络限制时(例如防火墙),访问/发布基于Java的服务;
Caucho的Hessian和Burlap:考虑网络限制时,通过HTTP访问/发布基于Java的服务。他俩唯一的区别是Hessian是二进制协议,而burlap是基于xml的。
Spring基于HTTP的远程服务:考虑网络限制,并希望使用基于xml或专有的序列化机制实现Java序列化时,访问/发布基于spring的服务。
使用JAX-RPC和JAX-WS的Web Service:访问/发布平台独立的、基于SOAP的web服务。
spring对这几种都提供了支持。
16、使用spring mvc创建REST API
近几年,以信息为中心的表述性状态转移(Representational State Transfer,REST)已成为替换传统SOAP Web服务的流行方案。SOAP(包含大量的xml命名空间)一般会关注行为和处理,而REST关注的是要处理的数据。
RPC是面向服务的,并关注行为和动作;而REST是面向资源的,强调描述应用程序的事务和名词。
REST就是将资源的状态以最合适客户端或服务端的形式从服务器端转移到客户端(或者反过来)。
在REST中,资源通过URL进行识别和定位。至于RESTful URL的结构并没有严格的规则,但是URL应该能够识别资源,而不是简单的发一条命令到服务器上。它关注的核心是事物,不是行为。
REST中会有行为,它们是通过HTTP方法来定义的,他会映射CRUD动作。
REST本质是面向资源。
使用@PathVariable注解,控制器能够处理参数化的URL(将变量输入作为URL的一部分);使用ContenNegotiatingViewResolver来选择最合适客户端的表述;借助@ResponseBody注解和各种HttpMethodConverter实现,能够替换基于视图的渲染方式。而@RequestBody和HttpMethodConverter实现可以将传入的HTTP数据转化为传入控制器处理方法的Java对象;借助RestTemplate,spring应用能够方便地使用REST资源。
17、spring消息:在spring中使用Java消息服务(Java Message Service,JMS)和高级消息队列协议(Advanced Message Queuing Protocol,AMQP)发送和接收消息;除了基本的消息发送和接收,还有spring对消息驱动POJO的支持,它是一种与EJB的消息驱动Bean(message-driven bean,MDB)类似的消息接收方式。
18、使用webSocket和STOMP实现消息功能
webSocket是两个应用之间全双工的通信通道。直接webSocket(或sockJS)就很类似于使用TCP套接字来编写web应用。因为没有高层级的线路协议(wire protocol),因此就需要我们定义应用之间所发送消息的语义,还需要确保连接的两端都能遵循这些语义。但我们并非必须要使用原生的WebSocket连接。就像HTTP在TCP套接字之上添加了请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式(frame-based wire format)层,用来定义消息的语义。
19、使用spring发送Email:spring mail抽象的核心是MailSender接口,它把Email发送给邮件服务器,由服务器进行邮件投递。
20、使用JMX管理spring bean:Java管理扩展(Java management Extensions ,JMX)使我们能够深入了解正在运行的应用并能在运行时改变应用的配置。使用JMX管理应用的核心组件是托管bean(managed bean,Mbean)。所谓的Mbean就是暴露特定方法的JavaBean,这些方法定义了管理接口。
JMX规范定义了4种类型的Mbean:
标准Mbean:它的管理接口是通过在固定的接口上执行反射确定的,bean类会实现这个接口。
动态Mbean:它的管理接口是在运行时通过调用DynamicMbean接口的方法来确定的。因为管理接口不是通过静态接口定义的,因此可以在运行时改变。
开放Mbean:它是一种特殊的动态Mbean,其属性和方法只限定于原始类型、原始类型的包装类以及可以分解为原始类型或原始类型包装类的任意类型。
模型Mbean:它也是一种特殊的动态Mbean,用于充当管理接口与受管资源的中介。它并不像它们所声明的那样来编写。它通常通过工厂生成,工厂会使用元信息来组装管理接口。
spring的JMX模块可以让我们将spring bean导出为模型Mbean,这样我们可以查看应用程序的内部情况并且能够更改配置——甚至在应用的运行期。
21、spring boot:这本书描述的太少了。