“A key element of Spring is infrastructural support at the application level: Spring focuses on the “plumbing” of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.”
Spring 起源
早在 2007 年,一个基于 Java 语言的开源框架正式发布,即 Spring。它是一个开源的轻量级 Java SE / Java EE 开发应用框架,其目的是简化企业级应用程序开发。在早期传统应用程序开发中,一个完整的应用是由一组相互协作的对象组成的。开发一个应用除了要开发业务逻辑外,最多的是关注如何使这些对象协作来完成所需要的功能,而且要低耦合、高内聚。如果能有种通过配置的方式来创建对象、管理对象之间的依赖关系,不需要我们自己通过工厂以及生成器来创建、管理对象之间的依赖关系,这样我们会减少许多重复性工作、加快开发速度,变相地帮助企业节约了资源。Spring 框架刚产生时便是解决这个问题的。
Spring 框架除了以上作用外,还提供了诸如通用日志记录、性能统计、安全控制、异常处理等面向切面的能力,还支持数据库事务管理。Spring 除了自己提供功能外,也提供粘合其它技术和框架的能力,从而让开发人员自由选用技术进行开发。现如今,Spring 已经成为一种生态,Spring Boot、Spring Cloud等为解决企业级开发问题提供了便捷的解决方案。
一切从 Bean 开始
早期的 Java 受到关注是因为可以使用 Applet 作为来开发Web应用,作为浏览器组件。JavaBean 规范最初针对 Java 定义了软件组件模型,这个规范规定了一整套编码策略,使简单的 Java 对象不仅可以被重用,还可以用来构建复杂的应用。但 JavaBean 在当时主要被用作构建窗体控件(当时的主流),相对于当时的 Delphi、VB、C++还是太简易,无法应用于实际工作。
复杂应用需要的事务、安全、分布式等服务,JavaBean在当时也未提供。所以到1998年 Sun 公司发布了 EJB 1.0 规范,该规范把Java组件的设计理念延伸至服务端,并提供了许多必须的企业级服务,但它也不再像早期的 JavaBean 那么简单了。实际上,除了名字是 EJB Bean 外,其它的已经与 JavaBean 关系不大了。
尽管当时很多系统基于 EJB 构建,但 EJB 从来没有实现最初的设想:简化开发。EJB的声明式编程的确简化了事务、安全等基础架构层面的开发,但在部署描述符和配套代码实现等方面变得异常复杂,被弃用是优胜劣汰的结果。基于 POJO 的编程模型提供了类似 EJB 的声明式编程,而没有引入任何 EJB 的复杂性。到 EJB 3.0 规范发布时,其它基于POJO的开发框架已经成为事实上的标准了,而 Spring 框架正是在这样的背景下产生的。
Spring 设计初衷
Spring 是为解决企业级应用开发的复杂性而设计,它可以做很多事。但归根到底支撑 Spring 的仅仅是少许的基本理念,而所有的这些基本理念都能可以追溯到一个最根本的使命:简化开发。对此,它主要采取了四个关键策略:
- 基于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 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。
DI 编程理念
Spring 设计的核心 org.springframework.beans 包(架构核心是 org.springframework.core 包),它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。
BeanFactory 最底层支持两个对象模型:
- 单例:提供了具有特定名称的全局共享实例对象,可以在查询时对其进行检索。Singleton 是默 认的也是最常用的对象模型。
- 原型:确保每次检索都会创建单独的实例对象。在每个用户都需要自己的对象时,采用原型模式。 Bean 工厂的概念是 Spring 作为 IOC 容器的基础,IOC 则将处理事情的责任从应用程序代码转移到 框架。
AOP 编程理念
面向切面编程,即 AOP,是一种编程思想,它允许开发人员对横切关注点或横切典型的职责分界线的 行为(例如日志和事务管理)进行模块化。AOP 的核心构造是切面,它将那些影响多个类的行为封装到可重用的模块中。
AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用 Spring AOP 编写的应用程序代码是松散耦合的。
AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。常用场景有:Authentication(权限认证)、Auto Caching(自动缓存处理)、Error Handling (统一错误处理)、Debugging(调试信息输出)、Logging(日志记录)、Transactions(事务处理) 等。
Spring 5 架构
Spring Framework 5 Runtime
Spring Moudle Denpendcy
核心模块
spring-core
IOC 与 DI 的最基本实现spring-beans Bean
工厂与 Bean 的装配spring-context
定义基础的 Spring Context 的上下文,即 IOC 容器spring-context-support
对 Spring IOC 容器的扩展支持及 IOC 子容器spring-context-indexer
Spring 的类管理组件和 Classpath 扫描spring-expression
Spring 表达式语言
切面编程
spring-aop
面向切面编程的应用模块,整合了 ASM、CGLIB、JDKProxyspring-aspects
集成 AspectJ、AOP 应用框架spring-instrument
动态 Class Loading 模块
数据访问与集成
spring-jdbc
Spring 提供的 JDBC 抽象框架的主要实现模块,用于简化 Spring JDBC 操作spring-tx
Spring JDBC 事务控制实现模块spring-orm
主要集成 Hibernate、Java Persistence API(JPA) 和 Java Data Objects(JDO)spring-oxm
将 Java 对象映射成 XML 数据,或者将 XML 数据映射成 Java 对象spring-jms
Java Messaging Service 能够发送和接收信息
Web 组件
spring-web
提供了最基础的 web 支持,主要建立于核心容器之上,通过 Servlet 或 Listeners 来初始化容器spring-webmvc
实现了 Spring MVC(model-view-controller) 的 Web 应用spring-websocket
主要是于 Web 前端全双工通讯的协议spring-webflux
一个新的非阻塞函数式 Reactive Web 框架,可以用来建立异步的、非阻塞的、事件驱动的服务
通信报文
spring-messaging
为 Spring 框架集成一些基础的报文传送应用(Spring 4 新加入的模块)
集成测试
spring-test
为测试提供支持
集成兼容
spring-framework-bom
Bill of Materials,解决 Spring 的不同模块依赖版本不同问题