[TOC]
Spring 的前世今生
Spring 是一个开源的轻量级 Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发
Spring 框架除了帮我们管理对象及其依赖关系,还提供像通用日志记录,性能统计,安全控制,异常处理等面向切面的能力,还能帮我管理最头疼的数据库事务,本身提供了一套简单的 JDBC 访问实现,提供与第三方数据访问框架集成(如 Hibernate,JPA),与各种 Java EE 技术整合(如 Java Mail,任务调度等等),提供一套自己的 Web 层框架 Spring MVC,而且还能非常简单的与第三方 Web 框架集成.从这里我们可以认为 Spring 是一个超级粘合大平台,除了自己提供功能外,还提供粘合其他技术和框架的能力,从而使我们可以更自由的选择到底使用什么技术进行开发
一切从 Bean 开始
Spring 的设计初衷
Spring 是为解决企业级应用开发的复杂性而设计,她可以做很多事.但归根到底支撑 Spring 的仅仅是少许的基本理念,而所有的这些基本理念都能可以追溯到一个最根本的使命:简化开发.Spring 则立志于全方面的简化 Java 开发.对此,她主要采取了 4 个关键策略:
- 基于 POJO 的轻量级和最小侵入性编程
- 通过依赖注入和面向接口松耦合
- 基于切面和惯性进行声明式编程
- 通过切面和模板减少样板式代码
而他主要是通过:面向 Bean(BOP),依赖注入(DI)以及面向切面(AOP)这三种方式来达成的
BOP 编程伊始
Spring 是面向 Bean 的编程(Bean Oriented Programming,BOP),Bean 在 Spring 中才是真正的主角.Bean 在 Spring 中作用就像 Object 对 OOP 的意义一样,Spring 中没有 Bean 也就没有 Spring 存在的意义.Spring 提供了 IOC 容器通过配置文件或者注解的方式来管理对象之间的依赖关系
控制反转(其中最常见的实现方式叫做依赖注入(Dependency Injection,DI),还有一种方式叫“依赖查找”(Dependency Lookup,DL),她在 C++,Java,PHP 以及.NET 中都运用.在最早的 Spring 中是包含有依赖注入方法和依赖查询的,但因为依赖查询使用频率过低,不久就被 Spring 移除了,所以在 Spring 中控制反转也被直接称作依赖注入),她的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器(在 Spring 框架中是 IOC 容器)负责将这些联系在一起
在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法
依赖注入的基本概念
Spring 设计的核心 org.springframework.beans 包(架构核心是 org.springframework.core 包),它的设计目标是与 JavaBean 组件一起使用.这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介.下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象.BeanFactory 也可以管理对象之间的关系
BeanFactory 最底层支持两个对象模型
- 单例:提供了具有特定名称的全局共享实例对象,可以在查询时对其进行检索.Singleton 是默认的也是最常用的对象模型
- 原型:确保每次检索都会创建单独的实例对象.在每个用户都需要自己的对象时,采用原型模式
Bean 工厂的概念是 Spring 作为 IOC 容器的基础.IOC 则将处理事情的责任从应用程序代码转移到框架
AOP 编程理念
面向切面编程,即 AOP,是一种编程思想,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化.AOP 的核心构造是方面(切面),它将那些影响多个类的行为封装到可重用的模块中
AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题.在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能.在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上.当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码.所以,用 SpringAOP 编写的应用程序代码是松散耦合的
AOP 的功能完全集成到了 Spring 事务管理,日志和其他各种特性的上下文中
AOP 编程的常用场景有:Authentication(权限认证),AutoCaching(自动缓存处理),ErrorHandling(统一错误处理),Debugging(调试信息输出),Logging(日志记录),Transactions(事务处理)等
Spring 中的编程思想总结
Spring 编程思想
Spring 思想 | 应用场景(特点) | 一句话归纳 |
---|---|---|
OOP | Object Oriented Programming(面向对象编程)用程序归纳总结生活中一切事物 | 封装,继承,多态 |
BOP | Bean Oriented Programming(面向 Bean 编程)面向 Bean(普通的 Java 类)设计程序,解放程序员 | —切从 Bean 开始 |
AOP | Aspect Oriented Programming(面向切面编程)找出多个类中有一定规律的代码,开发时拆开,运行时再合并,面向切面编程,即面向规则编程 | 解耦,专人做专事 |
IOC | Inversionof Control(控制反转)将 new 对象的动作交给 Spring 管理,并由 Spring 保存已创建的对象(IOC 容器) | 转交控制权(即控制权反转) |
DI/DL | Dependency Injection(依赖注入)或者 Dependency Look 叩(依赖查找)依赖注入,依赖查找,Spring 不仅保存自己创建的对象,而且保存对象与对象之间的关系.注入即赋值,主要三种方式构造方法,set 方法,直接赋值 | 赋值 |
Spring 注解编程
Spring Framework 1.x 注解驱动启蒙时代
从 SpringFramework 1.2.0 版本开始,开始支持 Annotation,虽然框架层面均已支持@managedResource 和@Transactional 等,但是其主要的还是以 XML 配置为准
Spring Framework 2.X 注解驱动过渡时代
Spring Framework 2.0 在 Annotation 支持方面添加了新的成员,@Required,数据相关的@Repository 及 AOP 相关的@Aspect 等,但同时提升了 XML 配置能力,即"可扩展的 XML 编写 ExtensibleXMLauthoring)〃,当然的,这种扩展能力的出现,无形中为 XML 的配置增加了筹码
Spring Framework 2.5 引入了新的骨架式 Annotation
@Service
@Controller,@RequestMapping 及@ModelAttribute
SpringFramework 2.5 还支持了 JSR-250(Java 规范)
©Resource 注入
@PostConstruct 替代<beaninit-method="..."/>
@PreDestroy 替代<beandestroy-method="..."/>
尽管 Spring Framework 2.X 时代提供了为数不少的注解,然而编程的手段却不多,最主要的原因在于框架层面仍未“直接"提供驱动注解的 Spring 应用上下文,并且仍需要 XML 驱动,<context:annotation-config>和<context:component-scan>
Spring Framework 3.x 注解驱动黄金时代
SpringFramework 3.x 是一个里程碑式的时代,3.0 除了提升 Spring 模式注解"派生"的层次性,首要任务是替换 XML 配置方式,引入配置类注解@Configuration,该注解是内建的@Component 的"派生"注解,遗憾的是,3.0 并没有引入<context:component-scan>的注解,而是选择过渡方案@ImportResource 和@Import,ImportResource 负责导入遗留的 XML 配置文件,Import 允许导入一个或多个类作为 SpringBean
3.0 引入 AnnotationConfigApplicationContext 最为前时代 ApplicationContext 的替代者,3.1 新引入注解@ComponentScan,替换 XML 的<context:component-scan>,成为全面进入注解驱动时代的一大步
Spring Framework 3.x 注解提升还体现在以下方面:
定义声明中,@Bean 允许使用注解@Role 设置其角色,使得 Spring 应用上下文具备条件化 Bean 定义的能力方面
@RequestHeader,@CookieVale 和@RequestPart 出现,使得不必使用 ServletAPI
以及配置属性源抽象 PropertySources,奠定了 SpringBoot 外部化配置的基础
配套的注解@Caching 和@Cacheable 极大简化数据缓存的开发
周期异步@Schedule 及异步 web 请求 DeferredResult
Spring Framework 4.x 注解驱动完善时代
3.1 开始提供@Profile 提供了配置化的条件组装,不过这方面还是比较单一的
4.0 开始,引入条件化注解@Conditional,通过自定义 Condition 实现配合,弥补之前版本条件化装配的短板
4.0 开始 Profile 反过来通过@Conditional 实现
Java 8 开始对提供@Repeatable,Framework 4.0 巧妙的兼容了 JSR-310.根据特性,将@PropertySources @ComponentScan 提升为可重复使用的注解@PropertySources,@ComponentScans
4.2 开始新增了事件监听器注解@EventListener,作为 ApplicationListener 接口编程的第二选择
@AliasFor 解除注解派生的时候冲突限制
在浏览器跨域资源访问方面引入@CrossOrigin,作为 CorsRegistry 替换注解方案
SpringFramework 5.x 注解驱动成熟时代
SpringFramework 5.0 作为 SpringBoot 2.0 的底层,注解驱动的性能提升不是那么明显.在 SpringBoot 应用场景中,大量使用@ComponentScan 扫描,导致 Spring 模式的注解解析时间耗时越长,面对这个问题,5.0 引入@Indexed,为 Spring 模式注解添加索引
Spring 5 系统架构
Spring 总共大约有 20 个模块,由 1300 多个不同的文件构成.而这些组件被分别整合在核心容器(CoreContainer),AOP(AspectOrientedProgramming)和设备支持(Instrmentation),数据访问及集成(DataAccess/Integeration),Web,报文发送(Messaging),Test,6 个模块集合中.以下是 Spring 5 的模块结构图:
组成 Spring 框架的每个模块集合或者模块都可以单独存在,也可以一个或多个模块联合实现.每个模块的组成和功能如下:
核心容器
由 spring-beans,spring-core,spring-context 和 spring-expression(SpringExpressionLanguage,SpEL)4 个模块组成
spring-core 和 spring-beans 模块是 Spring 框架的核心模块,包含了控制反转(Inversion Of Control,IOC)和依赖注入(Dependency Injection,DI).BeanFactory 接口是 Spring 框架中的核心接口,它是工厂模式的具体实现.BeanFactory 使用控制反转对应用程序的配置和依赖性规范与实际的应用程序代码进行了分离.但 BeanFactory 容器实例化后并不会自动实例化 Bean,只有当 Bean 被使用时 BeanFactory 容器才会对该 Bean 进行实例化与依赖关系的装配
spring-context 模块构架于核心模块之上,他扩展了 BeanFactory,为她添加了 Bean 生命周期控制,框架事件体系以及资源加载透明化等功能.此外该模块还提供了许多企业级支持,如邮件访问,远程访问,任务调度等,ApplicationContext 是该模块的核心接口,她的超类是 BeanFactory.与 BeanFactory 不同,ApplicationContext 容器实例化后会自动对所有的单实例 Bean 进行实例化与依赖关系的装配,使之处于待用状态
spring-context-support 模块是对 Spring IOC 容器的扩展支持,以及 IOC 子容器
spring-context-indexer 模块是 Spring 的类管理组件和 Classpath 扫描
spring-expression 模块是统一表达式语言(EL)的扩展模块,可以查询,管理运行中的对象,同时也方便的可以调用对象方法,操作数组,集合等.它的语法类似于传统 EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数.这种语言的特性是基于 Spring 产品的需求而设计,他可以非常方便地同 SpringIOC 进行交互
AOP 和设备支持
由 spring-aop,spring-aspects 和 spring-instrument 3 个模块组成
spring-aop 是 Spring 的另一个核心模块,是 AOP 主要的实现模块.作为继 OOP 后,对程序员影响最大的编程思想之一,AOP 极大地开拓了人们对于编程的思路.在 Spring 中,他是以 JVM 的动态代理技术为基础,然后设计出了一系列的 AOP 横切实现,比如前置通知,返回通知,异常通知等,同时,Pointcut 接口来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相关方法根据需求进行切入
spring-aspects 模块集成自 AspectJ 框架,主要是为 Spring AOP 提供多种 AOP 实现方法
spring-instrument 模块是基于 JAVASE 中的"java.lang.instrument"进行设计的,应该算是 AOP 的一个支援模块,主要作用是在 JVM 启用时,生成一个代理类,程序员通过代理类在运行时修改类的字节,从而改变一个类的功能,实现 AOP 的功能.在分类里把他分在了 AOP 模块下,在 Spring 官方文档里对这个地方也有点含糊不清,这里是纯个人观点
数据访问与集成
由 spring-jdbc,spring-tx,spring-orm,spring-jms 和 spring-oxm 5 个模块组成
spring-jdbc 模块是 Spring 提供的 JDBC 抽象框架的主要实现模块,用于简化 SpringJDBC 操作.主要是提供 JDBC 模板方式,关系数据库对象化方式,SimpleJdbc 方式,事务管理来简化 JDBC 编程,主要实现类是 JdbcTemplate,SimpleJdbcTemplate 以及 NamedParameterJdbcTemplate
spring-tx 模块是 SpringJDBC 事务控制实现模块.使用 Spring 框架,它对事务做了很好的封装,通过它的 AOP 配置,可以灵活的配置在任何一层;但是在很多的需求和应用,直接使用 JDBC 事务控制还是有其优势的.其实,事务是以业务逻辑为基础的;一个完整的业务应该对应业务层里的一个方法;如果业务操作失败,则整个事务回滚;所以,事务控制是绝对应该放在业务层的;但是,持久层的设计则应该遵循一个很重要的原则:保证操作的原子性,即持久层里的每个方法都应该是不可以分割的.所以,在使用 SpringJDBC 事务控制时,应该注意其特殊性
spring-orm 模块是 ORM 框架支持模块,主要集成 Hibernate,JavaPersistenceAPI(JPA)和 JavaDataObjects(JDO)用于资源管理,数据访问对象(DAO)的实现和事务策略
spring-oxm 模块主要提供一个抽象层以支撑 OXM(OXM 是 Object-to-XML-Mapping 的缩写,它是一个 O/M-mapper,将 java 对象映射成 XML 数据,或者将 XML 数据映射成 java 对象),例如:JAXB,Castor,XMLBeans,JiBX 和 XStream 等
spring-jms 模块(JavaMessagingService)能够发送和接收信息,自 SpringFramework 4.1 以后,他还提供了对 spring-messaging 模块的支撑
Web 组件
由 spring-web,spring-webmvc,spring-websocket 和 spring-webflux 4 个模块组成
spring-web 模块为 Spring 提供了最基础 Web 支持,主要建立于核心容器之上,通过 Servlet 或者 Listeners 来初始化 IOC 容器,也包含一些与 Web 相关的支持
spring-webmvc 模块众所周知是一个的 Web-Servlet 模块,实现了 SpringMVC(model-view-Controller)的 Web 应用
spring-websocket 模块主要是与 Web 前端的全双工通讯的协议
spring-webflux 是一个新的非堵塞函数式 ReactiveWeb 框架,可以用来建立异步的,非阻塞,事件驱动的服务,并且扩展性非常好
通信报文
即 spring-messaging 模块,是从 Spring 4 开始新加入的一个模块,主要职责是为 Spring 框架集成一些基础的报文传送应用
集成测试
即 spring-test 模块,主要为测试提供支持的,毕竟在不需要发布(程序)到你的应用服务器或者连接到其他企业设施的情况下能够执行一些集成测试或者其他测试对于任何企业都是非常重要的
集成兼容
即 spring-framework-bom 模块,BillofMaterials 解决 Spring 的不同模块依赖版本不同问题
各模块之间的依赖关系
Spring 官网对 Spring 5 各模块之间的关系也做了详细说明:
对 Spring 5 各模块做了一次系统的总结,描述模块之间的依赖关系,希望能对小伙伴们有所帮助
Spring 版本命名规则
Spring 版本命名规则
描述方式 | 说明 | 含义 |
---|---|---|
Snapshot | 快照版 | 尚不不稳定,尚处于开发中的版本 |
Release | 稳定版 | 功能相对稳定,可以对外发行,但有时间限制 |
GA | 正式版 | 代表广泛可用的穏定版(GeneralAvailability) |
M | 里程碑版 | (M 是 Milestone 的意思)具有一些全新的功能或是具有里程碑意义的版本 |
RC | 终测版 | ReleaseCandidate(最终测试),即樹乍为正式版发布 |