在 Google Guava 源码讲解中,我们讲到开发通用功能模块的一些比较普适的开发思想,比如产品意识、服务意识、代码质量意识、不要重复早轮子等。今天,我们剖析一下 Spring 框架背后的一些经典设计思想(或开发技巧)。这些设计思想并非 Spring 独有,都比较通用,能借鉴应用在很多通用功能模块的设计开发中。这也是我们学习 Spring 源码的价值所在。

1. 约定优于配置

在使用 Spring 开发的项目中,配置往往会比较复杂、繁琐。比如,我们利用 Spring MVC 来开发 Web 应用,需要配置每个 Controller 类以及 Controller 类中的接口对应的 URL。

如何来简化配置呢?一般来讲,有两种方法,一种是基于注解,另一种是基于约定。这两种配置方式在 Spring 中都有用到。Spring 在最小化配置方面做得淋漓尽致,有很多值得我们借鉴的地方。

基于注解的配置方式,我们在指定类上使用指定的注解,来替代集中的 XML 配置。比如,我们使用 @RequestMapping 注解,在 Controller 类或者接口上,标注对应的 URL;使用 @Transaction 注解表明支持事务等。

基于约定的配置方式,也常叫作“约定优于配置”或者“规约优于配置”(Convention over Configuration)。通过约定的代码结构或者命名来减少配置。说直白点,就是提供配置的默认值,优先使用默认值。程序员只需要设置那些偏离约定的配置就可以了

比如,在 Spring JPA(基于 ORM 框架、JPA 规范的基础上,封装的一套 JPA 应用框架)中,我们约定类名默认跟表名相同,属性名默认跟表字段名相同,String 类型对应数据库中的 varchar 类型,long 类型对应数据库中的 bigint 类型等等。

基于刚刚的约定,代码中定义的 Order 类就对应数据库中的“order”表。只有在偏离这一约定的时候,例如数据库中表命名为“order_info”而非“order”,我们才需要显示地去配置类与表的映射关系(Order 类 ->order_info 表)。

实际上,约定优于配置,很好地体现了“二八法则”。在平时的项目开发中,80% 的配置使用默认配置就可以了,只有 20% 的配置必须用户显式地去设置。所以,基于约定来配置,在没有牺牲配置灵活性的前提下,节省了我们大量编写配置的时间,省掉了很多不动脑子的纯体力劳动,提高了开发效率。除此之外,基于相同的约定来做开发,也减少了项目的学习成本和维护成本。

2. 低侵入、松耦合

框架的侵入性是衡量框架好坏的重要指标。所谓低侵入指的是,框架代码很少耦合在业务代码中。低侵入意味着,当我们要替换一个框架的时候,对原有的业务代码改动会很少。相反,如果一个框架是高度侵入的,代码高度侵入到业务代码中,那替换成另一个框架的成本将非常高,甚至几乎不可能。这也是一些长期维护的老项目,使用的框架、技术比较老旧,又无法更新的一个很重要的原因。

实际上,低侵入是 Spring 框架遵循的一个非常重要的设计思想。

Spring 提供的 IOC 容器,在不需要 Bean 继承任何父类或者实现任何接口的情况下,仅仅通过配置,就能将它们纳入进 Spring 的管理中。如果我们换一个 IOC 容器,也只是重新配置一下就可以了,原有的 Bean 都不需要任何修改。

除此之外,Spring 提供的 AOP 功能,也体现了低侵入的特性。在项目中,对于非业务功能,比如请求日志、数据采点、安全校验、事务等等,我们没必要将它们侵入进业务代码中。因为一旦侵入,这些代码将分散在各个业务代码中,删除、修改的成本就变得很高。而基于 AOP 这种开发模式,将非业务代码集中放到切面中,删除、修改的成本就变得很低了

3. 模块化、轻量级

我们知道,十几年前,EJB 是 Java 企业级应用的主流开发框架。但是,它非常臃肿、复杂,侵入性、耦合性高,开发、维护和学习成本都不低。所以,为了替代笨重的 EJB,Rod Johnson 开发了一套开源的 Interface21 框架,提供了最基本的 IOC 功能。实际上,Interface21 框架就是 Spring 框架的前身。

但是,随着不断的发展,Spring 现在也不单单只是一个只包含 IOC 功能的小框架了,它显然已经壮大成了一个“平台”或者叫“生态”,包含了各种五花八门的功能。尽管如此,但它也并没有重蹈覆辙,变成一个像 EJB 那样的庞大难用的框架。那 Spring 是怎么做到的呢?

这就要归功于 Spring 的模块化设计思想。我们先看一张图,如下所示,它是 Spring Framework 的模块和分层介绍图。


从图中我们可以看出,Spring 在分层、模块化方面做得非常好。每个模块都只负责一个相对独立的功能。模块之间关系,仅有上层对下层的依赖关系,而同层之间以及下层对上层,几乎没有依赖和耦合。除此之外,在依赖 Spring 的项目中,开发者可以有选择地引入某几个模块,而不会因为需要一个小的功能,就被强迫引入整个 Spring 框架。所以,尽管 Spring Framework 包含的模块很多,已经有二十几个,但每个模块都非常轻量级,都可以单独拿来使用。正因如此,到现在,Spring 框架仍然可以被称为是一个轻量级的开发框架。

4. 再封装、再抽象

Spring 不仅仅提供了各种 Java 项目开发的常用功能模块,而且还对市面上主流的中间件、系统的访问类库,做了进一步的封装和抽象,提供了更高层次、更统一的访问接口。比如,Spring 提供了 spring-data-redis 模块,对 Redis Java 开发类库(比如 Jedis、Lettuce)做了进一步的封装,适配 Spring 的访问方式,让编程访问 Redis 更加简单。

还有我们下节课要讲的 Spring Cache,实际上也是一种再封装、再抽象。它定义了统一、抽象的 Cache 访问接口,这些接口不依赖具体的 Cache 实现(Redis、Guava Cache、Caffeine 等)。在项目中,我们基于 Spring 提供的抽象统一的接口来访问 Cache。这样,我们就能在不修改代码的情况下,实现不同 Cache 之间的切换。

除此之外,还记得我们之前在模板模式中,讲过的 JdbcTemplate 吗?实际上,它也是对 JDBC 的进一步封装和抽象,为的是进一步简化数据库编程。不仅如此,Spring 对 JDBC 异常也做了进一步的封装。封装的数据库异常继承自 DataAccessException 运行时异常。这类异常在开发中无需强制捕获,从而减少了不必要的异常捕获和处理。除此之外,Spring 封装的数据库异常,还屏蔽了不同数据库异常的细节(比如,不同的数据库对同一报错定义了不同的错误码),让异常的处理更加简单。

总结

  • 核心就是要解耦

思考

  • 课堂讨论“约定优于配置”在很多开发场景中都有体现,比如 Maven、Gradle 构建工具,它们约定了一套默认的项目目录结构,除此之外,你还能想到体现这条设计思想的其他哪些开发场景吗?
  • 参照 Spring 的设计思想,分析一个你熟悉框架、类库、功能组件背后的设计思想。

参考

84 | 开源实战四(上):剖析Spring框架中蕴含的经典设计思想或原则

Spring 框架蕴含的设计思想相关推荐

  1. Spring框架系列之AOP思想

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.AOP概述 (1).什么是 AOP AOP 为 Aspect Oriented Progra ...

  2. Spring为什么这么火 之 Spring蕴含的设计思想

    目录 Spring是什么? 1.什么是IoC? 2.传统程序开发 3.控制反转式程序开发 4.理解Spring IoC 5.依赖注入[DI] 总结 前言 很多人说:"Java程序员都是Spr ...

  3. 轻松理解Spring框架的基本思想

    说起Spring框架,就不得不说J2EE的EJB.年龄稍大一些的Java程序员对J2EE的EJB还是记忆犹新的,当时使用EJB开发大型应用系统非常时髦,Java程序员无不以掌握EJB开发技术为自豪,程 ...

  4. Spring框架的设计理念与设计模式分析

    spring设计原理 Spring框架的设计理念与设计模式分析 2016-1-27 by Damon 摘要:Spring作为现在最优秀的框架之一,被广泛的使用并有很多对其分析的文章.本文将从另外一个视 ...

  5. Spring框架的事务管理及应用

    Spring框架简介 Spring框架是一个2003年2月才出现的开源项目,该开源项目起源自Rod Johnson在2002年末出版的<Expert One-on-One J2EE Design ...

  6. Spring框架入门:(非原著,转载)

    1.1.      耦合性和控制反转: 对象之间的耦合性就是对象之间的依赖性.对象之间的耦合越高,维护成本越高.因此,对象的设计应使类和构件之间的耦合最小. 例: public interface I ...

  7. 多图详解Spring框架的设计理念与设计模式

    Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的JDBC应用做过报道.本文将从另外一个视角试图剖析出Spring框架的作者设计Spring框架的骨骼架构的 ...

  8. 02.springMVC设计思想及springAOP

    MVC设计思想 历史问题:如果将大量的代码都写到一个方法中,后期维护不易 MVC说明: 1.M Model 数据层 数据处理/数据的持久化 2.V View 视图层 前端页面相关的内容(看到的内容) ...

  9. 深入学习Spring框架之一Spring的简要概括

    Java开发的春天 Spring框架最初的形成,来自于最初的一位Java领域的大牛-----Rod Jahnson.这位大牛所著的一本叫做<Expert One-on-One J2EE Desi ...

最新文章

  1. 通过仿真和综合认识JK触发器(Verilog HDL语言描述JK触发器)
  2. 1090 Highest Price in Supply Chain (25 分)【难度: 一般 / 知识点: 树的遍历】
  3. 实践 config drive - 每天5分钟玩转 OpenStack(170)
  4. 疫情之下“搜索+信息流”向上,百度移动生态的未来值得期待吗?
  5. python爬虫框架怎么安装_celery如何在python爬虫中安装?
  6. SQL Server与Oracle对比学习:权限管理(一)
  7. python (集合和深浅拷贝)
  8. 银行卡号每隔4位插入空格
  9. linux打印机驱动教程视频,Linux打印机配置wmv视频教程
  10. 改造家里的开关成为智能开关,保留原有开关控制,零火版,射频遥控器篇(二)
  11. unity下载模型到本地并加载
  12. vue+canvas如何实现b站萌系登录界面
  13. 自己做游戏(一)-PhotonServer配置
  14. onedrive教育版登录不上
  15. 给一个字符类型的数组chas和一个整数size,请把大小为size的左半区整体右移到右半区,右半区整体移动到左边。
  16. tinymce富文本编辑器扩展插件-设置段落间距
  17. Charles 常用基础功能使用方法
  18. php ean13,php生成EAN_13标准条形码实例_PHP教程
  19. Java 面试题 —— 强类型语言和弱类型语言的区别
  20. Java300集速学堂(5)

热门文章

  1. RTSP之主流安防厂家地址
  2. 利用vuex和localStorage实现vue菜单权限管理(笔记)
  3. go gorm 关联模式_Beego 结合 GORM 操作 Mysql 数据库
  4. python分布式计算框架_分布式计算框架Spark
  5. staruml 为类的属性指定数据类型_关于python的数据类型
  6. Android Studio的build.gradle里面的各种版本信息
  7. Android移动应用基础教程【服务】
  8. First集、Follow集
  9. jdbc basedao mysql_Java使用JDBC连接mysql、sqlserver、orcle数据库的baseDao类
  10. 查询计算机系的所有教师,用sql查询所有计算机系的教师编号和姓名