前言

上周剛看Spring IOC源碼的時候,和朋友高高興興的說,依賴注入真好用...

朋友:哪裡好用?

我說:不用new對象啊。

朋友:用new也不用寫全部啊,.var 快捷鍵也不慢啊。

我說:還可以解耦啊。

朋友:解耦幹嘛?

我想了想...是哦,我解耦幹啥???不解耦我照樣用啊???我炸了,陷入自己對自己的拷問。。。

自此我開始反思我學框架的方式是不是有問題。

因為想快點學完學新的東西,所以只學怎麼用和實現原理。

知其然,不知其所以然。

所以我重新找資料學習了IOC和AOP的設計思想,寫文加深印象。


正文

框架的核心作用簡單來說就是幾個

1.降低耦合,提高可維護性

2.提取復用代碼,提高編寫代碼效率

3.功能完備,且盡量輕量化

所以我認為,Spring在設計之初,所有的想法,都是圍繞著如何更好地實現這三個需求去製作的。在理解為什麼這麼設計的時候(看下面文章的時候),把設計理念和這三個核心作用對比,就很容易發現其中的奧妙。

說到Spring就要說兩大核心,IoC和AOP


IoC

控制反轉(Inversion of Control)

IoC一般來說分兩種實現方式

DL(依賴查找)

容器中的受控對象通過容器的API來查找自己所依賴的資源和協作對象。這種方式雖然降低了對象間的依賴,但是同時也使用到了容器的API,造成了我們無法在容器外使用和測試對象。 依賴查找是一種更加傳統的IoC實現方式。

這裡是使用容器的API內部實現反射創建對象,但是這也就導致了一個重要的問題,沒有加入容器的對象如果想要使用容器里的對象怎麼辦???難道要把所有的類全部加到容器里?這顯然是不方便的,所以Spring不使用DL而用DI

DI(依賴注入)

依賴注入就是將服務注入到使用它的地方。對象只提供普通的方法讓容器去決定依賴關係,容器全權負責組件的裝配,它會把符合依賴關係的對象通過屬性(JavaBean中的setter)或者是構造子傳遞給需要的對象。

對象的創建全權交給容器負責,容器內部通過反射(類載入器)實現。

和原來的創建方式比較

原本獲取實例對象的方式是這樣的:

People bean;
bean = new Student();

那這個時候我們要做的其實是三個事情

1.創建bean的棧空間

2.創建Student實例

3.bean變數指向Student實例

使用IoC以後:

[@Autowired](選用)
People bean;

這裡就做一件事

創建bean的棧空間

那麼實例對象怎麼辦呢?讓容器控制。相當於,我給你搭一個窩,容器決定你這個窩裡放不放,放什麼

這就是控制反轉

這麼做有什麼好處呢?

正常來說,資料里都是給你說降低耦合,但是這個降低耦合度的實際作用在哪裡呢?這裡我就要說到大學那個時候學到,但是完全不理解為什麼要這麼做的一種設計模式

開閉原則(Open Closed Principle)

——對修改關閉,對拓展開放

開閉原則

Java web中開閉原則(OCP)是指軟體實體應當對擴展開放,對修改關閉。對擴展開放意味著模塊的行為是可擴展的,對於修改的封閉則是對模塊的行為進行擴展時,不必改動模塊的源代碼或者二進位代碼。遵循開閉原則

開閉原則是一切設計原則的基礎,它是判斷面向對象設計是否正確的最基本的原理之一。它在軟體可用性上,非常靈活。它可以通過不斷的增加新的設計模塊滿足不斷變化的新需求!並且,由於開閉原則規定對軟體原來的模塊不要修改,因此不用擔心軟體的穩定性。如果一個軟體項目某些功能已經不符合要求了,我們可以重新開發,並且只需要將現有的功能替換掉。

關鍵:不必改動模塊的源代碼,通過不斷的增加新的設計模塊滿足不斷變化的新需求,不用擔心軟體的穩定性

這個設計理念也可以解釋為,主程序代碼一般不進行修改以保證項目的穩定性,主程序代碼對拓展功能是開放的以保證業務邏輯的靈活

夠清楚了么?不夠的話我解釋一遍

如果我是這麼寫的

People bean;
bean = new Student();

在實際需求中,如果我們對某個類需要進行修改,並且,這個類被很多其他類所依賴。那麼怎麼改呢?你是改Student類呢?還是新寫一個類再把項目所有的Student的類全改了名字呢??顯然都不合適,改Student類呢不符合開閉原則,改名字呢麻煩死了。

所以這個時候IoC就隆重登場了

People bean;

我這麼寫我根本就沒告訴你我裝的是啥,我隨時可以改我裝的東西,我只要告訴容器,不好意思,我現在該需求了,Student俺不想要你了,你先去容器里待著等著我分配崗位吧

這裡回歸三大作用之一:降低耦合,提高可維護性

那這個容器是啥?

容器就是一個管理組件的地方,把需要管理的組件放進容器里,容器會幫助你做很多很多很多很多很多很多事情。

去看Spring源碼就會知道,容器裡面有很多很多很多很多很多工廠,這些工廠幫你生產對象,再返回一個被加工過的對象還給你,所以說工廠設計模式是Spring用的最廣泛的設計模式。

順帶一提,放到容器里的對象最終會變成一張Map(String,Object)表儲存起來,用Key來取對象。

那這樣的話,我每次用容器我還要自己去搞那些工廠類么???

如果你這麼想那可太低估Spring了

這裡回歸三大作用之一 :提取復用代碼,提高編寫代碼效率

Spring希望你寫代碼越少越好,所以Spring搞了一個配置化...用XML文件去配置容器,工廠代碼幾乎看都看不見...

我們只要在XML里告訴容器什麼類叫什麼ID,什麼類存什麼東西即可,並且修改方便。

這樣嬸兒的

但是隨著放到容器的組件越來越多,要在XML里配置的東西也越來越多,還是麻煩,這個時候出現了註解(真是低估了程序員的懶惰程度...)

XML我也不用,我只要用註解指定哪個類放在容器里,類裡面哪個變數需要自動注入(如果有複雜要求,就在註解里加參數。)即可

這樣嬸兒的:

那這裡我又有個問題,為啥不直接棄用XML?

雖然我懶,但是我不能完不成工作呀

這裡回歸三大作用之一 :功能完備,且盡量輕量化

如果我想把jar包的類放到容器里去管理呢?我不可能去改jar包加個註解吧?

這個時候就只能用XML了。

現在最新形態應該是Springboot,反正就是越來越懶。


AOP(Aspect Oriented Programming)

AOP相對於IoC就好理解多了,但是有前置知識點要求:

動態代理設計模式(不知道的建議補一下)

OOP是面向對象編程,AOP同樣是一種設計思想,面向切面編程。

什麼叫切面?

我們在執行一個run()方法的時候,我們希望在run()方法的開始,返回值,出異常,結束的時候記錄一些日誌或者進行一些操作怎麼辦?

在run()方法里直接寫么?這侵入了方法本身的運行邏輯,是並不好的一種處理方式(某種意義上來說就是方法耦合了)

所以JDK為我們提供了Proxy代理類,通過動態代理模式,我們可以設計一種不侵入方法主體的方式去運行方法

這樣嬸兒的

但是,只使用這個的話,每個對象都要自己手動去寫一個動態代理類,那可太不符合能懶則懶的原則了

這裡回歸三大作用之一 :提取復用代碼,提高編寫代碼效率

去Spring.framework.aop包里看源碼其實就是用的動態代理模式

AOP的設計理念就是把動態代理模式擴大化,規範化。

同樣用XML或者註解的方式去配置動態代理模式的一些參數。

這裡最好了解AOP的一些術語

這裡AOP的使用步驟是這樣的

1.指定一個切面類

2.切面類指定切入點

3.寫要切入的代碼

這裡屬於AOP具體實現的內容了和標題不符就不繼續延伸了。

完...


推薦閱讀:
相关文章