javascript
Spring核心技术原理-(1)-通过Web开发演进过程了解一下为什么要有Spring?
一、知史可以明鑒
我們學(xué)習(xí)技術(shù)的時代趕上了最好的時代,跳過了很多前人經(jīng)常踩的坑,前人在踩坑的過程中總結(jié)了很多經(jīng)驗和教訓(xùn),而新時代的我們只是繼承了前人的經(jīng)驗和教訓(xùn),而忽略了這些采坑的過程,以至于我們面對很多新技術(shù)都不知道他是什么?他為什么存在?他為什么可以解決這個問題?更不知道如何掌握其原理!云里霧里一頭霧水!
交流群的很多小伙伴,常常私聊我讓我推薦一下學(xué)習(xí)SSM框架的視頻和資料,我首先會打開他的資料卡看一下他的年齡,如果超過了他這個年齡應(yīng)有的水平,我就會問他JSP+Servlet學(xué)了嗎?很多小伙伴的回答是簡單的學(xué)了一下,然后,我會給他一個關(guān)于JSP+Servlet的實戰(zhàn)項目,順便給他們找一些SSM的項目,并且建議他們首先看這個JSP+Servlet的實戰(zhàn)項目。
更有甚者,學(xué)了基礎(chǔ)之后就開始學(xué)習(xí)Spring Boot的,當(dāng)問他們Spring Boot是什么的時候,大致也可以回答出來“約定大于配置”,“用起來很簡單”,但是在細究其原理,也是吱吱嗚嗚,一知半解!如果我們沒有經(jīng)歷過Spring最開始繁瑣的配置、然后一步步精簡,根本體會不到為什么會有Spring Boot這個東西!
不先學(xué)習(xí)常見的設(shè)計模式直接看Spring、MyBatis等源碼,簡直就是一個找虐的過程!不掌握Servlet原理、基本的Tomcat容器技術(shù)上來就看Spring MVC源碼同樣也是一個打擊自信心的好地方!
學(xué)習(xí)是一個循序漸進的過程,不能急于求成,但也不能過分鉆牛角尖!不能再一個技術(shù)上停滯不前,也不能如”蜻蜓點水”一般寥寥掠過!同樣,如果你還沒有掌握好Servlet和簡單的設(shè)計模式我建議你先去查閱相關(guān)的資料進行系統(tǒng)的學(xué)習(xí)。
我也相信很多圖書或視頻等資料都忽略了講述為什么會有Spring的過程,要么是簡單概括并且痛斥EJB的各種弊端,要么就是只字不提,這是一種對讀者很不負責(zé)任的表現(xiàn),知史可以明鑒!因此,在進一步學(xué)習(xí)Spring核心原理之前,我們有必要介紹一下整個Web發(fā)展的簡單歷史,一步步引出為什么會有Spring!
二、Web發(fā)展簡史
老一輩的軟件開發(fā)人員一般經(jīng)歷了從Model1到Model2,然后到后來的三層模型,最后到現(xiàn)在的Spring Boot。如果從Model1到Model2說起到我們現(xiàn)在使用的Spring Boot為整個時間軸的話,大致可以分為4個階段:
(1)初級階段:使用Model1/Model2/三層模模型進行開發(fā);
(2)中級階段:使用EJB進行分布式應(yīng)用開發(fā),忍受重量級框架帶來的種種麻煩;
(3)高級階段:使用Spring春天帶給我們的美好,但是還要忍受很多繁瑣的配置;
(4)骨灰級階段:使用Spring Boot,暢享“預(yù)定大于配置”帶給我們的種種樂趣!
三、Web發(fā)展初級階段
1、Model1開發(fā)模式:
Model1的開發(fā)模式是:JSP+JavaBean的模式,它的核心是Jsp頁面,在這個頁面中,Jsp頁面負責(zé)整合頁面和JavaBean(業(yè)務(wù)邏輯),而且渲染頁面,它的基本流程如下:
相信很多小伙伴在剛學(xué)習(xí)Web的時候,肯定使用到了Model1開發(fā)模式,也就是我們的業(yè)務(wù)代碼、持久化代碼直接寫在Jsp頁面里邊,使用Jsp直接處理Web瀏覽器的請求,并使用JavaBean處理業(yè)務(wù)邏輯。
利用我們現(xiàn)在熟悉的MVC模型的思想去看,雖然編寫代碼十分容易,但Jsp混淆了MVC模型中的視圖層和控制層,高度耦合的結(jié)果是Jsp代碼十分復(fù)雜,后期維護困難!
2、Model2開發(fā)模式:
Model1雖然在一定程度上解耦了,但JSP依舊即要負責(zé)頁面控制,又要負責(zé)邏輯處理,職責(zé)不單一!此時Model2應(yīng)運而生,使得各個部分各司其職,Model2是基于MVC模式的。
Model2的開發(fā)模式是:Jsp+Servlet+JavaBean的模式,它和Model1不同的是,增加了Servlet,將調(diào)用頁面數(shù)據(jù),調(diào)用業(yè)務(wù)邏輯等工作放到了Servlet中處理,從而減輕了Jsp的工作負擔(dān)!它的基本流程如下:
Model2開發(fā)模式將Servlet的概念引入架構(gòu)體系中,使用它來分配視圖層Jsp的顯示頁面,同時調(diào)用模型層的JavaBean來控制業(yè)務(wù)邏輯。
3、Model1和Model2的區(qū)別:
Model1:簡單,適合小型項目的開發(fā),但是Jsp的職責(zé)過于繁重,職責(zé)分工不明確。在后期的維護工作中,必將為此付出代價!
Model2:相對于Model1來說,職責(zé)分工更為明確,在Model1的基礎(chǔ)上,抽取了Servlet層,體現(xiàn)了一個分層的思想,適合大型的項目開發(fā)!(當(dāng)時的評判標準是適合大型項目開發(fā)的,現(xiàn)在看起來已經(jīng)過時了!)
Model2看起來已經(jīng)盡善盡美了,盡管如此,他還不能稱之為一個比較完善的MVC設(shè)計模式!
4、Model1和Model2與三層的對比:
在Model2中,我們將Servlet抽取出單獨的一層,和Jsp協(xié)作完成用戶數(shù)據(jù)交互的工作,也就是表示層。那么作為三層結(jié)構(gòu)來說,又做了什么樣的改進呢?三層則是在此基礎(chǔ)上,將JavaBean再一次進行分割:業(yè)務(wù)邏輯、數(shù)據(jù)持久化,三層如下:
(1)表示層,JSP/Servlet;?
(2)業(yè)務(wù)邏輯層:業(yè)務(wù)規(guī)則;?
(3)持久化層:主要包裝持久化的邏輯 ;
各個的耦合性如下圖:
Model1、Model2、三層是在解耦的基礎(chǔ)上一步步進化而來,通過解耦我們可以進行進一步的抽象,以應(yīng)對現(xiàn)實需求的變動。
四、Web發(fā)展中級階段、高級階段和骨灰級階段
這一小節(jié)似乎有點應(yīng)付,對于中級階段,因為我沒有用過EJB,在這里不敢妄加評論,以免誤導(dǎo)大家。但是相信每一位接觸過Spring的小伙伴,都應(yīng)該知道Rod Johnson在2002年編寫的《Expert One-to-One J2EE Design and Development》一書,Rod 在本書中對J2EE正統(tǒng)框架臃腫、低效、脫離現(xiàn)實的種種學(xué)院派做法提出了質(zhì)疑,并以此書為指導(dǎo)思想,編寫了interface21框架,也就是后來的Spring。
對于高級階段和骨灰級階段是我們后期一系列文章的重點,本篇只作為一個階段劃分,不做過多的解釋,因此讓我們重新回到Web發(fā)展的初級階段。
對EJB有興趣的可以參考文章:http://www.uml.org.cn/j2ee/2009112011.asp
五、Web發(fā)展初級階段存在的問題
經(jīng)歷過初級階段的小伙伴肯定看得懂下邊的一個項目結(jié)構(gòu),一個簡單的MVC三層結(jié)構(gòu),使用JSP+Servlet+MySQL+JDBC技術(shù),面向接口編程:
1、面向接口編程的實例化對象
以用戶管理模塊為例,有一個UserDao接口,有一個接口的實現(xiàn)類UserDaoImpl,如下:
由于是面向接口編程,因此我們在每次使用UserDao的時候,都要進行實例化一次,實例化代碼如下:
UserDao userDao = new UserDaoImpl();- 1
我們在每次使用UserDao的時候都需要進行實例化,當(dāng)然不僅僅有UserDao需要進行實例化,還有很多需要進行實例化的,舉例如下:
可以看出,每一個方法中都需要進行實例化我們需要用到的接口的實現(xiàn)類,這就會存在大量的實例化對象,并且他們的生命周期可能就是從方法的調(diào)用開始到方法的調(diào)用結(jié)束為止,加大了GC回收的壓力!
2、使用單利模式的一次改進
了解設(shè)計模式的可能會想到使用單利模式的方式來解決這個問題,以此來避免大量重復(fù)的創(chuàng)建對象,但是我們還要考慮到眾多的這種對象的創(chuàng)建都需要改成單利模式的話,是一個耗時耗力的操作。
對于這個系統(tǒng)來說,如果都把這種面向接口的對象實現(xiàn)類轉(zhuǎn)換為單利模式的方式的話,大概也要寫十幾個或者上百個這種單例模式代碼,而對于一個單利模式的寫法來說,往往是模板式的代碼,以靜態(tài)內(nèi)部類的方式實現(xiàn)代理模式如下:
可以看出,這種方式有兩個問題:
(1)業(yè)務(wù)代碼與單利模式的模板代碼放在一個類里,耦合性較高;?
(2)大量重復(fù)的單利模式的模板代碼;
從上述可以看出,使用的單利模式雖然從性能上有所提高,但是卻加重了我們的開發(fā)成本。因此只會小規(guī)模的使用,例如我們操作JDBC的Utils對象等。
3、我們開發(fā)中遇到的痛點
從上述代碼的演進過程我們可以看得出來,我們即需要一個單利的對象來避免系統(tǒng)中大量重復(fù)對象的創(chuàng)建和銷毀,又不想因為使用單利模式造成大量重復(fù)無用的模板代碼和代碼的耦合!
(突然想到一個段子,想和大家分享一下:產(chǎn)品經(jīng)理在給甲方匯報方案的時候說了兩種方案:一種是實用的,一種是美觀的,問甲方希望選擇哪一種?甲方說:有沒有即實用又美觀的!)
4、我們還能怎么做
作為學(xué)院派的書生來說,我們可能會聯(lián)想到“數(shù)據(jù)庫連接池”,我們在獲取數(shù)據(jù)庫連接的時候會從這個池子中拿到一個連接的,假設(shè)這個數(shù)據(jù)庫連接池很特殊,有且只能有N個數(shù)據(jù)庫連接,并且每一個連接對象都不同(假設(shè)),那么這個不就相當(dāng)于每一個連接都是單利的了嗎?既可以避免大量對象的創(chuàng)建,也可以實現(xiàn)不會出現(xiàn)大量重復(fù)性的模板代碼。
因此,這里應(yīng)該有一個大膽的想法,我們是否可以建立一個池子,將我們的接口實現(xiàn)類對象放入到這個池子中,我們在使用的時候直接從這個池子里邊取就行了!
5、這個池子
如果我們要創(chuàng)建這個池子,首先要確定需要把哪些對象放進這個池子,通過怎樣的方式放進去,放進去之后如何進行管理,如何進行獲取,池子中的每一個對象的生命周期是怎么樣的等等這些東西都是我們需要考慮到的!
6、恭喜你
如果你已經(jīng)了解了上述Web演進的過程,以及我們想要創(chuàng)建的這個池子,那么恭喜你!你已經(jīng)打開了Spring核心原理的大門了!
上述我們想要創(chuàng)建的池子其實就是Spring容器的雛形,將接口實現(xiàn)類的對象放進池子進行管理的過程其實也是Spring IOC依賴注入、控制反轉(zhuǎn)的雛形!
Spring的依賴注入/控制反轉(zhuǎn)就是從我們的配置文件或注解中的得到我們需要進行注入到Spring容器的實現(xiàn)類的信息,Spring IOC通過這些配置信息創(chuàng)建一個個單利的對象并放入Spring容器中,Spring容器可以看做是一個集合保存著我們的這些對象。
7、小總結(jié)
上文中主要從一個切入點探討了一下為什么有Spring,以及介紹了一下Spring IOC和Spring容器的基本雛形概念,當(dāng)然還可以從其他方面進行切入。這里沒有進一步探討AOP的概念,對于新入門的小伙伴來說,這個確實有必要討論一下,也決定在后續(xù)文章中由淺入深的探討一下,而對于老手來說,其實我上邊寫的基本上是浪費大家時間的!
六、總結(jié)
從歷史的角度來說,不同時期的大革命在爆發(fā)之前,都會有一個蓄謀已久的“導(dǎo)火線”!Spring的出現(xiàn),同樣順應(yīng)了歷史發(fā)展潮流,正式由于那個時期J2EE開發(fā)標準的種種弊端造就了Spring的出現(xiàn)!即使不是Spring,同樣也會有其他類似的產(chǎn)品出現(xiàn),只不過歷史選擇了Spring,Spring順應(yīng)了歷史!沒有切膚之痛,是不會體會到Spring帶給我們的樂趣與快感!
同樣的,每個時代都會有每一個時代的問題,Spring也是!正如十年前我們的計算機可能帶不動一款游戲,今天我們的計算機也有可能帶不動一款如今的游戲,同樣十年后的計算機也會有一款他帶不動的游戲出現(xiàn)!以一種發(fā)展的眼光去看Spring,就可以很好的理解Spring Boot是以一種什么樣的角色出現(xiàn)在我們的面前了!
時代選擇了Spring,同樣Spring也被這個時代所選擇著!你我只有不停的進步,不停地學(xué)習(xí)才能跟上這個時代!
總結(jié)
以上是生活随笔為你收集整理的Spring核心技术原理-(1)-通过Web开发演进过程了解一下为什么要有Spring?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot应用之消息队列rab
- 下一篇: Spring boot 集成工作流flo