Spring是Java平台的一个开源的全栈应用程序框架和控制反转容器实现。 该框架的一些核心功能理论上可用于任何Java应用,但Spring还为基于Java企业版平台构建的 Web 应用提供了大量的拓展支持。虽然Spring没有直接实现任何的编程模型,但它已经在 Java社区中广为流行,基本上完全代替了企业级JavaBeans(EJB)模型。
Spring框架以 Apache License 2.0 开源许可协议的形式发布,该框架最初由 Rod Johnson 以及 Juergen Hoeller 等人开发。
一、版本历史
第一版由 Rod Johnson 开发,并在2002年10月发布在 Expert One-on-One J2EE Design and Development 一书中。2003年6月,Spring Framework 第一次发布在 Apache 2.0 许可证下。2004年3月,发布了里程碑的版本1.0,2004年9月以及2005年3月,又发布了新的里程碑版本。2006年,Spring Framework 获得了 Jolt 生产力奖 和 JAX 创新奖。
2006年10月发布Spring 2.0,2007年11月 Spring 2.5,2009年12月 Spring 3.0,2011年 Spring 3.1,2013年11月 Spring 3.2.5,2013年12月发布了4.0版本。值得注意的是,Spring 4.0 版本中增加了对 Java SE 8, Groovy 2, Java EE 7 的一些方面以及 WebSocket 的支持。
2017年9月 Spring Framework 正式发布了 5.0 版本,此版本引入了 Spring WebFlux,一个高性能、响应式、异步的 Web 框架。Spring 5.0 重点加强了对函数式编程、响应式程序设计(reactive programming)的支持能力,是一个非常大的进步。
二、核心功能模块
- 强大的基于 JavaBeans 的采用控制反转(Inversion of Control,IoC)原则的配置管理,使得应用程序的组建更加简易快捷。
- 一个可用于 Java EE 等运行环境的核心 Bean工厂。
- 数据库事务的一般化抽象层,允许声明式(Declarative)事务管理器,简化事务的划分使之与底层无关。
- 内建的针对 JTA 和单个 JDBC 数据源的一般化策略,使Spring的事务支持不要求 Java EE 环境,这与一般的 JTA 或者 EJB CMT 相反。
- JDBC 抽象层提供了有针对性的异常等级(不再从SQL异常中提取原始代码),简化了错误处理,大大减少了程序员的编码量。再次利用JDBC时,你无需再写出另一个‘终止‘(finally)模块。并且面向 JDBC 的异常与 Spring 通用数据访问对象(Data Access Object)异常等级相一致。
- 以资源容器,DAO 实现和事务策略等形式与 Hibernate,JDO 和 MyBatis 、SQL Maps 集成。利用控制反转机制全面解决了许多典型的Hibernate集成问题。所有这些全部遵从 Spring 通用事务处理和通用数据访问对象异常等级规范。
- 灵活的基于核心 Spring功能的MVC网页应用程序框架。开发者通过策略接口将拥有对该框架的高度控制,因而该框架将适应于多种呈现(View)技术,例如JSP、FreeMarker、Velocity、Thymeleaf等。值得注意的是,Spring中间层可以轻易地结合于任何基于 MVC 框架的网页层,例如 Struts、WebWork 或 Tapestry。
- 提供诸如事务管理等服务的AOP框架。
- 在设计应用程序 Model时,MVC模式(例如Struts)通常难于给出一个简洁明了的框架结构。Spring 却具有能够让这部分工作变得简单的能力。程序开发员们可以使用Spring的JDBC抽象层重新设计那些复杂的框架结构。
三、从Bean开始
最早的1996年开始可以使用Java的Applet来开发Web应用,作为浏览器组件。但开发者们很快就发现这个新兴的语言还能做更多的事情。同年12月,Sun公司发布了当时还名不见经传但后来人尽皆知的 JavaBean 1.00-A 规范。
复杂的应用通常需要事务、安全、分布式等服务的支持,但JavaBean并未直接提供。所以到了 1998年 3 月,Sun公司发布了EJB1.0规范,该规范把Java组件的设计理念延伸到了服务器端,并提供了许多必须的企业级服务,但他也不再像早期的JavaBean 那么简单了。实际上,除了名字叫 EJB Bean以外,其他的和 JavaBean关系不大了。
尽管现实中有很多系统是基于EJB构建的,但EJB从来没有实现它最初的设想:简化开发。EJB 的声明式编程模型的确简化了很多基础架构层面的开发,例如事务和安全;但另一方面 EJB 在部署描述符和配套代码实现等方面变得异常复杂。随着时间的推移,很多开发者对 EJB 已经不再抱有幻想,开始寻求更简洁的方法。
客观地讲,EJB 的发展甚至促进了基于 POJO 的编程模型。到了 EJB 3 规范发 布时,其他基于 POJO的开发架构已经成为事实的标准了,而Spring框架也就是在这样的大环境下出现的。
四、Spring能给我们带来什么
4.1 Spring简化开发的四个基本策略
- 基于POJO的轻量级和最小侵入性编程
- 通过依赖注入和面向接口松耦合
- 基于切面和惯性进行声明式编程
- 通过切面和模板减少样板式代码
Spring主要通过:面向Bean(BOP)、依赖注入(DI)和面向切面(AOP)这三种方式来达成的。
AOP、IOC和DI之间的关系
4.2 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 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。
4.3 依赖注入
Spring 设计的核心 org.springframework.beans包(架构核心是org.springframework.core包),它的设计目标是与JavaBean组件一起使用。这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。
BeanFactory 最底层支持两个对象模型:
-
单例:提供了具有特定名称的全局共享实例对象,可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。
-
原型:确保每次检索都会创建单独的实例对象。在每个用户都需要自己的对象时,采用原型模式。
Bean 工厂的概念是 Spring作为IOC容器的基础。IOC则将处理事情的责任从应用程序代码转移到框架。
4.4 AOP 编程
面向切面编程,即 AOP,是一种编程思想,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP的核心构造是方面(切面),它将那些影响多个类的行为封装到可重用的模块中。
AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在AOP方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是Java类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用SpringAOP编写的应用程序代码是松散耦合的。
AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。
AOP 编程的常用场景有:Authentication(权限认证)、Auto Caching(自动缓存处理)、Error Handling (统一错误处理)、Debugging(调试信息输出)、Logging(日志记录)、Transactions(事务处理) 等。
五、Spring5的系统架构
Spring 总共大约有 20个模块,由1300多个不同的文件构成。而这些组件被分别整合在核心容器(Core Container)、AOP(Aspect Oriented Programming)和设备支持(Instrmentation)、数据访问 及集成(Data Access/Integeration)、Web、报文发送(Messaging)、Test,6 个模块集合中。以下是 Spring 5 的模块结构图: