《Spring源碼解析(一)》Spring框架的前世此生以及對Spring的宏觀認識

本文學習目標

一、掌握 Spring 的基本架構及各子模塊之間的依賴關係。前端

二、瞭解 Spirng 的發展歷史,啓發思惟。java

三、對 Spring 造成一個總體的認識,爲以後的深刻學習作鋪墊。程序員

四、瞭解 Spring 版本升級的規律,從而應用到本身的系統升級版本命名。web

Spring 的前世此生

相信經歷過不使用框架開發 Web 項目的 70 後、80 後都會有如此感觸,現在的程序員開發項目過輕鬆 了,基本只須要關心業務如何實現,通用技術問題只須要集成框架即可。面試

早在 2007 年,一個基於 Java 語言的開源框架正式發佈,取了一個很是有活力且美好的名字,叫作Spring。spring

它是一個開源的輕量級Java SE(Java 標準版本)/Java EE(Java 企業版本)開發應用框架,其目的是用於簡化企業級應用程序開發。數據庫

應用程序是由一組相互協做的對象組成。而在傳統應用程序開發中,一個完整的應用是由一組相互協做的對象組成。express

因此開發一個應用除了要開發業務邏輯以外,最多的是關注如何使這些對象協做來完成所需功能,並且要低耦合、高聚合。業務邏輯開發是不可避免的,那若是有個框架出來幫咱們來建立對象及管理這些對象之間的依賴關係。編程

可能有人說了,好比「抽象工廠、工廠方法模式」不也能夠幫咱們建立對象,「生成器模式」幫咱們處理對象間的依賴關係,不也能完成這些功能嗎?設計模式

但是這些又須要咱們建立另外一些工廠類、生成器類,咱們又要而外管理這些類,增長了咱們的負擔,若是能有種經過配置方式來建立對象,管理對象之間依賴關係,咱們不須要經過工廠和生成器來建立及管理對象之間的依賴關係,這樣咱們是否是減小了許多工做,加速了開發,能節省出不少時間來幹其餘事。

Spring框架剛出來時主要就是來完成這個功能。

Spring 框架除了幫咱們管理對象及其依賴關係,還提供像通用日誌記錄、性能統計、安全控制、異常處理等面向切面的能力,還能幫我管理最頭疼的數據庫事務,自己提供了一套簡單的 JDBC 訪問實現,提供與第三方數據訪問框架集成(如 Hibernate、JPA),與各類 Java EE 技術整合(如 Java Mail、任務調度等等),提供一套本身的 Web 層框架 Spring MVC、並且還能很是簡單的與第三方 Web 框架集成。

從這裏咱們能夠認爲 Spring 是一個超級粘合大平臺,除了本身提供功能外,還提供粘合其餘技術和框架的能力,從而使咱們能夠更自由的選擇到底使用什麼技術進行開發。

並且無論是 JAVA SE(C/S 架構)應用程序仍是 JAVA EE(B/S 架構)應用程序均可以使用這個平臺進行開發。現在的 Spring 已經再也不是一個框架,早已成爲了一種生態。

SpringBoot 的便捷式開發實現了零配置,SpringCloud 全家桶,提供了很是方便的解決方案。接下來,讓咱們來深刻探討 Spring 到底能給咱們帶來什麼?

一切從 Bean 開始

說到 Bean 這個概念,還得從 Java 的起源提及。

早在 1996 年,Java 還只是一個新興的、初出茅廬的編程語言。人們之因此關注她僅僅是由於,可使用 Java 的 Applet 來開發 Web 應用,做爲瀏覽器組件。

但開發者們很快就發現這個新興的語言還能作更多的事情。

與以前的全部語言不一樣,Java 讓模塊化構建複雜的系統成爲可能(當時的軟件行業雖然在業務上日新月異,但當時開發用的是傳統的面向過程開發思想,軟件的開發效率一直踟躕不前。

伴隨着業務複雜性的不斷加深,開發也變得愈加困難。

其實,當時也是 OOP 思想飛速發展的時期,她在 80 年代末被提出,成熟於 90 年代,現今大多數編程語言都已是面向對象的)。

同年 12 月,Sun 公司發佈了當時還名不見經傳但後來人盡皆知的 JavaBean 1.00-A 規範。早期的JavaBean 規範針對於 Java,她定義了軟件組件模型。

這個規範規定了一整套編碼策略,使簡單的 Java對象不只能夠被重用,並且還能夠輕鬆地構建更爲複雜的應用。

儘管 JavaBean 最初是爲重用應用組件而設計的,但當時他們倒是主要用做構建窗體控件,畢竟在 PC 時代那纔是主流。

但相比於當時正如日中天的 Delphi、VB 和 C++,它看起來仍是太簡易了,以致於沒法勝任任何"實際的"工做須要。

複雜的應用一般須要事務、安全、分佈式等服務的支持,但 JavaBean 並未直接提供。

因此到了 1998年 3 月,Sun 公司發佈了 EJB 1.0 規範,該規範把 Java 組件的設計理念延伸到了服務器端,並提供了許多必須的企業級服務,但他也再也不像早期的 JavaBean 那麼簡單了。

實際上,除了名字叫 EJB Bean之外,其餘的和 JavaBean 關係不大了。

儘管現實中有不少系統是基於 EJB 構建的,但 EJB 歷來沒有實現它最初的設想:簡化開發。

EJB 的聲明式編程模型的確簡化了不少基礎架構層面的開發,例如事務和安全;

但另外一方面 EJB 在部署描述符和配套代碼實現等方面變得異常複雜。隨着時間的推移,不少開發者對 EJB 已經再也不抱有幻想,開始尋求更簡潔的方法。

如今 Java 組件開發理念從新迴歸正軌。新的編程技術 AOP 和 DI 的不斷出現,他們爲 JavaBean 提供了以前 EJB 才能擁有的強大功能。這些技術爲 POJO 提供了相似 EJB 的聲明式編程模型,而沒有引入 任何 EJB 的複雜性。

當簡單的 JavaBean 足以勝任時,人們便不肯編寫笨重的 EJB 組件了。

客觀地講,EJB 的發展甚至促進了基於 POJO 的編程模型。引入新的理念,最新的 EJB 規範相比以前的規範有了史無前例的簡化,但對不少開發者而言,這一切的一切都來得太遲了。

到了 EJB 3 規範發佈時,其餘基於 POJO 的開發架構已經成爲事實的標準了,而 Spring 框架也就是在這樣的大環境下出現的。

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 最底層支持兩個對象模型。

1,單例:提供了具備特定名稱的全局共享實例對象,能夠在查詢時對其進行檢索。Singleton 是默認的也是最經常使用的對象模型。

2,原型:確保每次檢索都會建立單獨的實例對象。在每一個用戶都須要本身的對象時,採用原型模式。

Bean 工廠的概念是 Spring 做爲 IOC 容器的基礎。

IOC 則將處理事情的責任從應用程序代碼轉移到框架。

AOP 編程理念

面向切面編程,即 AOP,是一種編程思想,它容許程序員對橫切關注點或橫切典型的職責分界線的行爲(例如日誌和事務管理)進行模塊化。

AOP 的核心構造是方面(切面),它將那些影響多個類的行爲封裝到可重用的模塊中。

AOP 和 IOC 是補充性的技術,它們都運用模塊化方式解決企業應用程序開發中的複雜問題。

在典型的面向對象開發方式中,可能要將日誌記錄語句放在全部方法和 Java 類中才能實現日誌功能。

在 AOP方式中,能夠反過來將日誌服務模塊化,並以聲明的方式將它們應用到須要日誌的組件上。

固然,優點就是 Java 類不須要知道日誌服務的存在,也不須要考慮相關的代碼。因此,用 Spring AOP 編寫的應用程序代碼是鬆散耦合的。

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 的模塊結構圖:

組成 Spring 框架的每一個模塊集合或者模塊均可以單獨存在,也能夠一個或多個模塊聯合實現。每一個模塊的組成和功能以下:

核心容器

由spring-beans、spring-core、spring-context和spring-expression(Spring Expression Language, 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 產品的需求而設計,他能夠很是方便地同 Spring IOC 進行交互。

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 模塊是基於 JAVA SE 中的"java.lang.instrument"進行設計的,應該算是 AOP的一個支援模塊,主要做用是在 JVM 啓用時,生成一個代理類,程序員經過代理類在運行時修改類的字節,從而改變一個類的功能,實現 AOP 的功能。在分類裏,我把他分在了 AOP 模塊下,在 Spring 官方文檔裏對這個地方也有點含糊不清,這裏是純我的觀點。

數據訪問與集成

由 spring-jdbc、spring-tx、spring-orm、spring-jms 和 spring-oxm 5 個模塊組成。

spring-jdbc 模塊是 Spring 提供的 JDBC 抽象框架的主要實現模塊,用於簡化 Spring JDBC 操做 。

主要是提供 JDBC 模板方式、關係數據庫對象化方式、SimpleJdbc 方式、事務管理來簡化 JDBC 編程,主要實現類是 JdbcTemplate、SimpleJdbcTemplate 以及 NamedParameterJdbcTemplate。

spring-tx 模塊是 Spring JDBC 事務控制實現模塊。使用 Spring 框架,它對事務作了很好的封裝,經過它的 AOP 配置,能夠靈活的配置在任何一層;可是在不少的需求和應用,直接使用 JDBC 事務控制仍是有其優點的。其實,事務是以業務邏輯爲基礎的;一個完整的業務應該對應業務層裏的一個方法;

若是業務操做失敗,則整個事務回滾;因此,事務控制是絕對應該放在業務層的;可是,持久層的設計則應該遵循一個很重要的原則:保證操做的原子性,即持久層裏的每一個方法都應該是不能夠分割的。

因此,在使用 Spring JDBC 事務控制時,應該注意其特殊性。

Web 組件

由 spring-web、spring-webmvc、spring-websocket 和 spring-webflux 4 個模塊組成。

spring-web 模塊爲 Spring 提供了最基礎 Web 支持,主要創建於核心容器之上,經過 Servlet 或者 Listeners 來初始化 IOC 容器,也包含一些與 Web 相關的支持。

spring-webmvc 模塊衆所周知是一個的 Web-Servlet 模塊,實現了 Spring MVC (model-view-Controller)的 Web 應用。

spring-websocket 模塊主要是與 Web 前端的全雙工通信的協議。

spring-webflux 是一個新的非堵塞函數式 Reactive Web 框架,能夠用來創建異步的,非阻塞,事件驅動的服務,而且擴展性很是好。

通訊報文

即 spring-messaging 模塊,是從 Spring4 開始新加入的一個模塊,主要職責是爲 Spring 框架集成一些基礎的報文傳送應用。

集成測試

即 spring-test 模塊,主要爲測試提供支持的,畢竟在不須要發佈(程序)到你的應用服務器或者鏈接到其餘企業設施的狀況下可以執行一些集成測試或者其餘測試對於任何企業都是很是重要的。

集成兼容

即 spring-framework-bom 模塊,Bill of Materials.解決 Spring 的不一樣模塊依賴版本不一樣問題。

各模塊之間的依賴關係

我對 Spring5 各模塊作了一次系統的總結,描述模塊之間的依賴關係,但願能對小夥伴們有所幫助。

接下來的《深刻Spring5源碼系列》中,咱們將深刻了解 Spring 的核心模塊功能。

基本學習順序爲:從 spring-core 入手, 其次是 spring-beans 和 spring-aop,隨後是 spring-context,再其次是 spring-tx 和 spring-orm, 最後是 spring-web 和其餘部分。

Spring 版本命名規則

版本號的格式爲 X.Y.Z(又稱 Major.Minor.Patch):

X 表示主版本號, 當 API 的兼容性變化時, X 需遞增。

Y 表示次版本號, 當增長功能時(不影響 API 的兼容性), Y 需遞增。

Z 表示修訂號, 當作 Bug 修復時(不影響 API 的兼容性), Z 需遞增。

詳細的規則以下:

X, Y, Z 必須爲非負整數,且不得包含前導零,必須按數值遞增,如 1.9.0 -> 1.10.0 -> 1.11.0。

0.Y.Z 的版本號代表軟件處於初始開發階段, 意味着 API 可能不穩定; 1.0.0 代表版本已有穩定的 API。

當 API 的兼容性變化時, X 必須遞增, Y 和 Z 同時設置爲 0;

當新增功能(不影響 API 的兼容性)或者 API 被標記爲 Deprecated 時, Y 必須遞增, 同時 Z 設置爲 0; 當進行 bug fix 時, Z 必須遞增。

先行版本號(Pre-release)意味該版本不穩定, 可能存在兼容性問題, 其格式爲: X.Y.Z.[a-c][正整數], 如 1.0.0.a1, 1.0.0.b99, 1.0.0.c1000。

開發版本號經常使用於 CI-CD, 格式爲 X.Y.Z.dev[正整數], 如 1.0.1.dev4。

版本號的排序規則爲依次比較主版本號、 次版本號和修訂號的數值, 如 1.0.0 < 1.0.1 < 1.1.1 < 2.0.0;

對於先行版本號和開發版本號, 有: 1.0.0.a100 < 1.0.0, 2.1.0.dev3 < 2.1.0; 當存在字母時, 以 ASCII 的排序來比較, 如 1.0.0.a1 < 1.0.0.b1。

常見的版本修飾詞

Snapshot: 版本表明不穩定、尚處於開發中的版本

Alpha: 內部版本

Beta: 測試版

Demo: 演示版

Enhance: 加強版

Free: 自由版

Full Version: 完整版,即正式版

LTS: 長期維護版本

Release: 發行版

RC: 即將做爲正式版發佈

Standard: 標準版

Ultimate: 旗艦版

Upgrade: 升級版

Spring 版本修飾詞

Release:穩定版本

GA:普遍可用的穩定版(General Availability)

M:里程碑版本(Milestone)具備一些全新的功能或是具備里程碑意義的版本

RC:即將做爲正式版發佈 (Release Candidate)

Spring Cloud 微服務精彩系列

  1. 阿里面試官問我:到底知不知道什麼是Eureka,此次,我沒沉默
  2. 萬字詳解Ribbon架構,針對面試高頻題多角度細說Ribbon
  3. 什麼是Hystrix,阿里技術最終面,遺憾的倒在Hystrix面前!
  4. 2萬字好文全方位深刻學習SpringCloud Fegin,面試不在彷徨
  5. Zuul,據說SpringCloud不許備要我了,但是爲何面試還要每天問我?
  6. 全網最全講解 Spring Cloud Gateway,認真看完這一篇就夠了!

相關文章
相關標籤/搜索