在 Java 世界里,Spring 框架已經(jīng)幾乎成為項目開發(fā)的必備框架。作為如此優(yōu)秀和受歡迎的開源項目,它是我們源碼閱讀的首選材料之一,不管是設(shè)計思想,還是代碼實現(xiàn),都有很多值得我們學(xué)習(xí)的地方。接下來,我們就詳細講講 Spring 框架中蘊含的設(shè)計思想、原則和模式。因為內(nèi)容比較多,我分三部分來講解。
- 第一部分,我們講解 Spring 框架中蘊含的經(jīng)典設(shè)計思想或原則。
- 第二部分,我們講解 Spring 框架中用來支持擴展的兩種設(shè)計模式。
- 第三部分,我們總結(jié)羅列 Spring 框架中用到的其他十幾種設(shè)計模式。
今天,我們就講下第一部分:Spring 框架中蘊含的一些設(shè)計思想或原則,這其中就包括:約定大于配置、低侵入松耦合、模塊化輕量級等。這些設(shè)計思想都很通用,掌握之后,我們可以借鑒用到其他框架的開發(fā)中。
話不多少,讓我們正式開始今天的學(xué)習(xí)吧!
Spring 框架簡單介紹
考慮到你可能不熟悉 Spring,我這里對它做下簡單介紹。我們常說的 Spring 框架,是指 Spring Framework 基礎(chǔ)框架。Spring Framework 是整個 Spring 生態(tài)(也被稱作 Spring 全家桶)的基石。除了 Spring Framework,Spring 全家桶中還有更多基于 Spring Framework 開發(fā)出來的、整合更多功能的框架,比如 Spring Boot、Spring Cloud。
在 Spring 全家桶中,Spring Framework 是最基礎(chǔ)、最底層的一部分。它提供了最基礎(chǔ)、最核心的 IOC 和 AOP 功能。當然,它包含的功能還不僅如此,還有其他比如事務(wù)管理(Transactions)、MVC 框架(Spring MVC)等很多功能。下面這個表格,是我從 Spring 官網(wǎng)上找的,關(guān)于 Spring Framework 的功能介紹,你可以大略地看下有個印象。
在 Spring Framework 中,Spring MVC 出鏡率很高,經(jīng)常被單獨拎出來使用。它是支持 Web 開發(fā)的 MVC 框架,提供了 URL 路由、Session 管理、模板引擎等跟 Web 開發(fā)相關(guān)的一系列功能。
Spring Boot 是基于 Spring Framework 開發(fā)的。它更加專注于微服務(wù)開發(fā)。之所以名字里帶有“Boot”一詞,跟它的設(shè)計初衷有關(guān)。Spring Boot 的設(shè)計初衷是快速啟動一個項目,利用它可以快速地實現(xiàn)一個項目的開發(fā)、部署和運行。Spring Boot 支持的所有功能都是圍繞著這個初衷設(shè)計的,比如:集成很多第三方開發(fā)包、簡化配置(比如,規(guī)約優(yōu)于配置)、集成內(nèi)嵌 Web 容器(比如,Tomcat、Jetty)等。
單個的微服務(wù)開發(fā),使用 Spring Boot 就足夠了,但是,如果要構(gòu)建整個微服務(wù)集群,就需要用到 Spring Cloud 了。Spring Cloud 主要負責(zé)微服務(wù)集群的服務(wù)治理工作,包含很多獨立的功能組件,比如 Spring Cloud Sleuth 調(diào)用鏈追蹤、Spring Cloud Config 配置中心等。
從 Spring 看框架的作用
如果你使用過一些框架來做開發(fā),你應(yīng)該能感受到使用框架開發(fā)的優(yōu)勢。這里我稍微總結(jié)一下。利用框架的好處有:解耦業(yè)務(wù)和非業(yè)務(wù)開發(fā)、讓程序員聚焦在業(yè)務(wù)開發(fā)上;隱藏復(fù)雜實現(xiàn)細節(jié)、降低開發(fā)難度、減少代碼 bug;實現(xiàn)代碼復(fù)用、節(jié)省開發(fā)時間;規(guī)范化標準化項目開發(fā)、降低學(xué)習(xí)和維護成本等等。實際上,如果要用一句話來總結(jié)一下的話,那就是簡化開發(fā)!
對于剛剛的總結(jié),我們再詳細解釋一下。
相比單純的 CRUD 業(yè)務(wù)代碼開發(fā),非業(yè)務(wù)代碼開發(fā)要更難一些。所以,將一些非業(yè)務(wù)的通用代碼開發(fā)為框架,在項目中復(fù)用,除了節(jié)省開發(fā)時間之外,也降低了項目開發(fā)的難度。除此之外,框架經(jīng)過多個項目的多次驗證,比起每個項目都重新開發(fā),代碼的 bug 會相對少一些。而且,不同的項目使用相同的框架,對于研發(fā)人員來說,從一個項目切換到另一個項目的學(xué)習(xí)成本,也會降低很多。
接下來,我們再拿常見的 Web 項目開發(fā)來舉例說明一下。
通過在項目中引入 Spring MVC 開發(fā)框架,開發(fā)一個 Web 應(yīng)用,我們只需要創(chuàng)建 Controller、Service、Repository 三層類,在其中填寫相應(yīng)的業(yè)務(wù)代碼,然后做些簡單的配置,告知框架 Controller、Service、Repository 類之間的調(diào)用關(guān)系,剩下的非業(yè)務(wù)相關(guān)的工作,比如,對象的創(chuàng)建、組裝、管理,請求的解析、封裝,URL 與 Controller 之間的映射,都由框架來完成。
不僅如此,如果我們直接引入功能更強大的 Spring Boot,那將應(yīng)用部署到 Web 容器的工作都省掉了。Spring Boot 內(nèi)嵌了 Tomcat、Jetty 等 Web 容器。在編寫完代碼之后,我們用一條命令就能完成項目的部署、運行。
Spring 框架蘊含的設(shè)計思想
在 Google Guava 源碼講解中,我們講到開發(fā)通用功能模塊的一些比較普適的開發(fā)思想,比如產(chǎn)品意識、服務(wù)意識、代碼質(zhì)量意識、不要重復(fù)早輪子等。今天,我們剖析一下 Spring 框架背后的一些經(jīng)典設(shè)計思想(或開發(fā)技巧)。這些設(shè)計思想并非 Spring 獨有,都比較通用,能借鑒應(yīng)用在很多通用功能模塊的設(shè)計開發(fā)中。這也是我們學(xué)習(xí) Spring 源碼的價值所在。
1. 約定優(yōu)于配置
在使用 Spring 開發(fā)的項目中,配置往往會比較復(fù)雜、繁瑣。比如,我們利用 Spring MVC 來開發(fā) Web 應(yīng)用,需要配置每個 Controller 類以及 Controller 類中的接口對應(yīng)的 URL。
如何來簡化配置呢?一般來講,有兩種方法,一種是基于注解,另一種是基于約定。這兩種配置方式在 Spring 中都有用到。Spring 在最小化配置方面做得淋漓盡致,有很多值得我們借鑒的地方。
基于注解的配置方式,我們在指定類上使用指定的注解,來替代集中的 XML 配置。比如,我們使用 @RequestMapping 注解,在 Controller 類或者接口上,標注對應(yīng)的 URL;使用 @Transaction 注解表明支持事務(wù)等。
基于約定的配置方式,也常叫作“約定優(yōu)于配置”或者“規(guī)約優(yōu)于配置”(Convention over Configuration)。通過約定的代碼結(jié)構(gòu)或者命名來減少配置。說直白點,就是提供配置的默認值,優(yōu)先使用默認值。程序員只需要設(shè)置那些偏離約定的配置就可以了。
比如,在 Spring JPA(基于 ORM 框架、JPA 規(guī)范的基礎(chǔ)上,封裝的一套 JPA 應(yīng)用框架)中,我們約定類名默認跟表名相同,屬性名默認跟表字段名相同,String 類型對應(yīng)數(shù)據(jù)庫中的 varchar 類型,long 類型對應(yīng)數(shù)據(jù)庫中的 bigint 類型等等。
基于剛剛的約定,代碼中定義的 Order 類就對應(yīng)數(shù)據(jù)庫中的“order”表。只有在偏離這一約定的時候,例如數(shù)據(jù)庫中表命名為“order_info”而非“order”,我們才需要顯示地去配置類與表的映射關(guān)系(Order 類 ->order_info 表)。
實際上,約定優(yōu)于配置,很好地體現(xiàn)了“二八法則”。在平時的項目開發(fā)中,80% 的配置使用默認配置就可以了,只有 20% 的配置必須用戶顯式地去設(shè)置。所以,基于約定來配置,在沒有犧牲配置靈活性的前提下,節(jié)省了我們大量編寫配置的時間,省掉了很多不動腦子的純體力勞動,提高了開發(fā)效率。除此之外,基于相同的約定來做開發(fā),也減少了項目的學(xué)習(xí)成本和維護成本。
2. 低侵入、松耦合
框架的侵入性是衡量框架好壞的重要指標。所謂低侵入指的是,框架代碼很少耦合在業(yè)務(wù)代碼中。低侵入意味著,當我們要替換一個框架的時候,對原有的業(yè)務(wù)代碼改動會很少。相反,如果一個框架是高度侵入的,代碼高度侵入到業(yè)務(wù)代碼中,那替換成另一個框架的成本將非常高,甚至幾乎不可能。這也是一些長期維護的老項目,使用的框架、技術(shù)比較老舊,又無法更新的一個很重要的原因。
實際上,低侵入是 Spring 框架遵循的一個非常重要的設(shè)計思想。
Spring 提供的 IOC 容器,在不需要 Bean 繼承任何父類或者實現(xiàn)任何接口的情況下,僅僅通過配置,就能將它們納入進 Spring 的管理中。如果我們換一個 IOC 容器,也只是重新配置一下就可以了,原有的 Bean 都不需要任何修改。
除此之外,Spring 提供的 AOP 功能,也體現(xiàn)了低侵入的特性。在項目中,對于非業(yè)務(wù)功能,比如請求日志、數(shù)據(jù)采點、安全校驗、事務(wù)等等,我們沒必要將它們侵入進業(yè)務(wù)代碼中。因為一旦侵入,這些代碼將分散在各個業(yè)務(wù)代碼中,刪除、修改的成本就變得很高。而基于 AOP 這種開發(fā)模式,將非業(yè)務(wù)代碼集中放到切面中,刪除、修改的成本就變得很低了。
3. 模塊化、輕量級
我們知道,十幾年前,EJB 是 Java 企業(yè)級應(yīng)用的主流開發(fā)框架。但是,它非常臃腫、復(fù)雜,侵入性、耦合性高,開發(fā)、維護和學(xué)習(xí)成本都不低。所以,為了替代笨重的 EJB,Rod Johnson 開發(fā)了一套開源的 Interface21 框架,提供了最基本的 IOC 功能。實際上,Interface21 框架就是 Spring 框架的前身。
但是,隨著不斷的發(fā)展,Spring 現(xiàn)在也不單單只是一個只包含 IOC 功能的小框架了,它顯然已經(jīng)壯大成了一個“平臺”或者叫“生態(tài)”,包含了各種五花八門的功能。盡管如此,但它也并沒有重蹈覆轍,變成一個像 EJB 那樣的龐大難用的框架。那 Spring 是怎么做到的呢?
這就要歸功于 Spring 的模塊化設(shè)計思想。我們先看一張圖,如下所示,它是 Spring Framework 的模塊和分層介紹圖。
從圖中我們可以看出,Spring 在分層、模塊化方面做得非常好。每個模塊都只負責(zé)一個相對獨立的功能。模塊之間關(guān)系,僅有上層對下層的依賴關(guān)系,而同層之間以及下層對上層,幾乎沒有依賴和耦合。除此之外,在依賴 Spring 的項目中,開發(fā)者可以有選擇地引入某幾個模塊,而不會因為需要一個小的功能,就被強迫引入整個 Spring 框架。所以,盡管 Spring Framework 包含的模塊很多,已經(jīng)有二十幾個,但每個模塊都非常輕量級,都可以單獨拿來使用。正因如此,到現(xiàn)在,Spring 框架仍然可以被稱為是一個輕量級的開發(fā)框架。
4. 再封裝、再抽象
Spring 不僅僅提供了各種 Java 項目開發(fā)的常用功能模塊,而且還對市面上主流的中間件、系統(tǒng)的訪問類庫,做了進一步的封裝和抽象,提供了更高層次、更統(tǒng)一的訪問接口。
比如,Spring 提供了 spring-data-redis 模塊,對 Redis Java 開發(fā)類庫(比如 Jedis、Lettuce)做了進一步的封裝,適配 Spring 的訪問方式,讓編程訪問 Redis 更加簡單。
還有我們下節(jié)課要講的 Spring Cache,實際上也是一種再封裝、再抽象。它定義了統(tǒng)一、抽象的 Cache 訪問接口,這些接口不依賴具體的 Cache 實現(xiàn)(Redis、Guava Cache、Caffeine 等)。在項目中,我們基于 Spring 提供的抽象統(tǒng)一的接口來訪問 Cache。這樣,我們就能在不修改代碼的情況下,實現(xiàn)不同 Cache 之間的切換。
除此之外,還記得我們之前在模板模式中,講過的 JdbcTemplate 嗎?實際上,它也是對 JDBC 的進一步封裝和抽象,為的是進一步簡化數(shù)據(jù)庫編程。不僅如此,Spring 對 JDBC 異常也做了進一步的封裝。封裝的數(shù)據(jù)庫異常繼承自 DataAccessException 運行時異常。這類異常在開發(fā)中無需強制捕獲,從而減少了不必要的異常捕獲和處理。除此之外,Spring 封裝的數(shù)據(jù)庫異常,還屏蔽了不同數(shù)據(jù)庫異常的細節(jié)(比如,不同的數(shù)據(jù)庫對同一報錯定義了不同的錯誤碼),讓異常的處理更加簡單。文章來源:http://www.zghlxwxcb.cn/news/detail-518994.html
重點回顧
好了,今天的內(nèi)容到此就講完了。我們一塊來總結(jié)回顧一下,你需要重點掌握的內(nèi)容。
借助 Spring 框架,我們總結(jié)了框架的作用:解耦業(yè)務(wù)和非業(yè)務(wù)開發(fā)、讓程序員聚焦在業(yè)務(wù)開發(fā)上;隱藏復(fù)雜實現(xiàn)細節(jié)、降低開發(fā)難度、減少代碼 bug;實現(xiàn)代碼復(fù)用、節(jié)省開發(fā)時間;規(guī)范化標準化項目開發(fā)、降低學(xué)習(xí)和維護成本等。實際上,如果要用一句話來總結(jié)一下的話,那就是簡化開發(fā)!
除此之外,我們還重點講解了 Sping 背后蘊含的一些經(jīng)典設(shè)計思想,主要有:約定優(yōu)于配置,低侵入、松耦合,模塊化、輕量級,再封裝、再抽象。這些設(shè)計思想都比較通用,我們可以借鑒到其他框架的開發(fā)中。文章來源地址http://www.zghlxwxcb.cn/news/detail-518994.html
課堂討論
- “約定優(yōu)于配置”在很多開發(fā)場景中都有體現(xiàn),比如 Maven、Gradle 構(gòu)建工具,它們約定了一套默認的項目目錄結(jié)構(gòu),除此之外,你還能想到體現(xiàn)這條設(shè)計思想的其他哪些開發(fā)場景嗎?
- 參照 Spring 的設(shè)計思想,分析一個你熟悉框架、類庫、功能組件背后的設(shè)計思想。
到了這里,關(guān)于【開源與項目實戰(zhàn):開源實戰(zhàn)】84 | 開源實戰(zhàn)四(上):剖析Spring框架中蘊含的經(jīng)典設(shè)計思想或原則的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!