淺談Spring的相關概念性問題 IOC DI AOP 工廠模式 單例

在我的理想觀點中,軟件的開發分爲前端開發和後端開發;前端開發就是用Vue、Ext等JavaScript框架做出各種華麗的界面,直接面向用戶,把用戶的相關操作轉化成指定形式,發給後端;後端開發就是從前端接取數據,對數據庫進行增刪改查。

其實一年前老師就讓我們接觸一下SSM框架,可那時的我還在沉迷Java的文件讀寫、GUI那一塊,還有就是微信公衆號。我在前幾天看着視頻學者搭建了SSM的開發環境,大致看懂了代碼,然後翻博客,找知乎,初步理解了SSM中一些概念性問題,這裏做一個整理。

Spring本質上是一個庫,它提供了軟件框架的功能,使軟件之間的邏輯更加清晰,配置更靈活,Spring使用AOP和IoC,而AOP和IoC是一種思想。

在總結的時候可能用到其他博客的內容,參考網址寫在最後面。

 

IOC 控制反轉

書本定義

原先需要實現的對象創建、維護對象間的依賴關係,反轉給容器幫忙實現。

看不懂很正常,請接着看下去

應用背景

採用面向對象方法設計的軟件系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。

例如我們家裏掛的時鐘,秒針轉一圈之後,分針轉一小格;同理分針轉一圈,時針轉一大格。

在面向對象編程中,即當秒針轉了一圈的時候,秒針對象就要new一個分針對象,然後讓分針的值+1,然後秒針的值歸零。我們可以看出,秒針對象的正常運行需要分針對象,我們可以說是一種依賴關係,即秒針依賴於分針。(假設對象爲單例)

如果我們打開時鐘的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在錶盤上產生正確的時間。上圖中描述的就是這樣的一個齒輪組,它擁有多個獨立的齒輪,這些齒輪相互齧合在一起,協同工作,共同完成某項任務。我們可以看到,在這樣的齒輪組中,如果有一個齒輪出了問題,就可能會影響到整個齒輪組的正常運轉。

面向對象編程中的“耦合關係”,就好比齒輪組中齒輪之間的齧合關係。對象之間的耦合關係是無法避免的,也是必要的,這是協同工作的基礎。但是,伴隨着編程開發的規模越來越龐大,對象之間的依賴關係也越來越複雜,經常會出現對象之間的多重依賴性關係,因此,對象之間耦合度過高的系統,必然會出現牽一髮而動全身的情形。

所以我們必須要想辦法優化這一個方面,即所謂實現對象之間的“解耦”,它是爲了解決對象之間的耦合度過高的問題。好了,IOC這就來了。

IOC是什麼

藉助於“第三方”實現具有依賴關係的對象之間的解耦

spring IOC容器負責創建Bean,並通過容器將Bean注入到需要Bean的對象上。

還是剛剛的例子,由於引進了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個對象沒有了耦合關係,齒輪之間的傳動全部依靠“第三方”了,全部對象的控制權全部上繳給“第三方”IOC容器,所以,IOC容器成了整個系統的關鍵核心,它起到了一種類似“粘合劑”的作用,把系統中的所有對象粘合在一起發揮作用,如果沒有這個“粘合劑”,對象與對象之間會彼此失去聯繫。

這時候,A、B、C、D這4個對象之間已經沒有了耦合關係了,秒針轉了一圈,只需要告訴IOC容器,我轉了一圈了,IOC就會把分針的值加1;這樣的話,當你在實現A的時候,根本無須再去考慮B、C和D了,對象之間的依賴關係已經降低到了最低程度。所以,如果真能實現IOC容器,對於系統開發而言,參與開發的每一成員只要實現自己的事情就可以了,別人的跟我沒有任何關係

具體實現

還是剛剛的例子,設對象A爲時鐘的秒針,對象B是時鐘的分針。

軟件系統在沒有引入IOC容器之前,對象A依賴於對象B,那麼對象A在初始化或者運行到某一點的時候,自己必須主動去創建對象B或者使用已經創建的對象B。無論是創建還是使用對象B,控制權都在自己手上。在引入IOC容器之後,這種情形就完全改變了。由於IOC容器的加入,對象A與對象B之間失去了直接聯繫,所以,當對象A運行到需要對象B的時候,IOC容器會主動創建一個對象B注入到對象A需要的地方。對象A獲得依賴對象B的過程,由主動行爲變爲了被動行爲,控制權顛倒過來了。


就比如,我們是如何找女朋友的?大學裏,我們會到處去看哪裏有長得漂亮身材又好的mm,然後打聽她們的興趣愛好、微信、電話……,想辦法認識她們,投其所好送其所要,然後嘿嘿……這個過程是很繁瑣的,我們要在需要談戀愛的時候,去手動new一個出來。傳統的編程開發也是這樣,在一個對象中,如果要使用另外的對象,就必須自己new一個,使用完之後還要將對象銷燬。

那麼有了IOC之後,有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚介。婚介管理了很多男男女女的資料,我可以向婚介告知一個需求,告訴它我想找個什麼樣的女朋友,比如身高一米七,等等等等,然後婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛就行了。簡單明瞭,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。

DI 依賴注入

通過引入IOC容器,利用依賴關係注入的方式,實現對象之間的解耦。

通俗來講,在軟件系統運行過程中,對象A需要依賴對象B的時候,IOC容器動態的向對象A傳輸它需要的對象B這個傳輸的過程叫做注入,注入了什麼?就是注入了依賴,所以全稱叫做依賴注入。

比如說對象A某個時候需要連接數據庫(A需要依賴Connection),原本需要自己new一個Connection對象,有了IOC之後,我們只需要告訴IOC,我需要Connection;IOC會在適當的時候創建Connection對象,至於什麼時候創建,則麼創建,不需要讓對象A知道。那麼IOC在向對象A傳遞Connection對象,我們叫做注入,就好比打針一樣,把Connection對象注入到對象A中。

還有一個概念——反射:它允許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性。

spring就是通過反射來實現依賴注入的。

單例模式

即一個類實例化的對象唯一,例如Windows中的任務管理器,只能打開一個。具體可通過相關代碼來實現,比如在類內部實例化私有對象,通過public方法調用該對象。

簡單工廠模式

實質是由一個工廠類根據傳入的參數, 動態決定應該創建哪一個產品類,就是暴力的if-else。原先是通過new方法實例化,現在只需要實例化一個工廠類,傳入一個參數告訴工廠類你要什麼,就可以獲取你要的對象。比如傳入一個"dog"字符串,返回給你一個狗對象。

工廠模式

假設有10個產品,那麼該工廠模式有1個抽象父類工廠Factory(可以是接口、抽象類、具體類),該父類包含未實現工廠方法;接着有10個具體工廠子類,一一對應這10個產品類,因爲父類工廠Factory未實現的工廠方法由子類來負責實現,不同具體工廠子類可以創建不同具體產品。工廠模式使得一個類的實例化延遲到其子類。

Spring Bean 的創建是典型的工廠模式, 這一系列的 Bean 工廠, 也即 IOC 容器爲開發者管理對象間的依賴關係提供了很多便利和基礎服務, 在 Spring 中有許多的 IOC 容器的實現供用戶選擇和使用。

 

AOP面向切面編程

書面定義

AOP就好比一把刀,在程序運行的時候,可以隨意的插入和拔出,在插入拔出的位置(切面)可以爲所欲爲,比如記錄日誌等。利用AOP可以實現對業務邏輯的各個部分進行分離,降低耦合度。

解析

就比如上圖,當我們在手機銀行APP進行取款、查詢、轉賬的時候,都會先讓你驗證身份吧,我們可以把這個“驗證身份”過程提取出來,即畫一個類似“切面”的綠線。即在一系列縱向的控制流程中,把那些相同的子流程提取成一個橫向的面

那麼我們能不能把這個公共功能提取出來,包裝一下呢?有了AOP之後,我們可以先把主要流程寫完,然後反過來在另一個地方寫驗證身份的代碼,然後告訴Spring要插入到哪些地方即可,而不需要你自己Copy過去。

AOP的主要思想是先實現程序的整體框架,然後再具體的編寫每個部分的詳細代碼,最後插到整體框架裏面


比如1個main函數調用了100個方法,現在要求在執行調用方法之前輸出一句日誌

最暴力的方法就是每個方法複製粘貼syso即可。

採用面向對象思想,就是編寫一個日誌打印方法,該方法執行這些日誌打印操作,然後在每個業務方法之前加入這句方法調用

但是如果要求我們在業務方法結束時再打印一些日誌呢,是不是還要去每個業務方法結束時加一遍?這樣始終不是辦法,而且我們總是在改業務方法,在業務方法裏面摻雜了太多的其他操作,侵入性太高。這時候AOP就起到作用了,我們可以編寫一個切面類(Aspect),在其中的方法中來編寫橫切邏輯(如打印日誌),然後通過配置或者註解的方式來聲明該橫切邏輯起作用的位置,從而不需要改變原先代碼即可實現所需要的功能。

 

實現方式

Spring AOP採用的是JDK動態代理,在運行期間對業務方法進行增強,所以不會生成新類。

 

參考網址列表:

參考網址1

參考網址2

參考網址3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章