javascript
Spring IOC/DI和AOP
一、分享Iteye的開濤對Ioc的精彩講解
首先要分享的是Iteye的開濤這位技術牛人對Spring框架的IOC的理解,寫得非常通俗易懂,以下內容全部來自原文,原文地址:http://jinnianshilongnian.iteye.com/blog/1413846
1.1、IoC是什么
Ioc—Inversion of Control,即“控制反轉”,不是什么技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什么,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
●誰控制誰,控制什么:傳統Java SE程序設計,我們直接在對象內部通過new進行創建對象,是程序主動去創建依賴對象;而IoC是有專門一個容器來創建這些對象,即由Ioc容器來控制對 象的創建;誰控制誰?當然是IoC 容器控制了對象;控制什么?那就是主要控制了外部資源獲取(不只是對象包括比如文件等)。
●為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙創建及注入依賴對象;為何是反轉?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。
用圖例說明一下,傳統程序設計如圖2-1,都是主動去創建相關對象然后再組合起來:
圖1-1 傳統應用程序示意圖
當有了IoC/DI的容器后,在客戶端類中不再主動去創建這些對象了,如圖2-2所示:
圖1-2有IoC/DI容器后程序結構示意圖
1.2、IoC能做什么
IoC 不是一種技術,只是一種思想,一個重要的面向對象編程的法則,它能指導我們如何設計出松耦合、更優良的程序。傳統應用程序都是由我們在類內部主動創建依賴對象,從而導致類與類之間高耦合,難于測試;有了IoC容器后,把創建和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,所以對象與對象之間是 松散耦合,這樣也方便測試,利于功能復用,更重要的是使得程序的整個體系結構變得非常靈活。
其實IoC對編程帶來的最大改變不是從代碼上,而是從思想上,發生了“主從換位”的變化。應用程序原本是老大,要獲取什么資源都是主動出擊,但是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC容器來創建并注入它所需要的資源了。
IoC很好的體現了面向對象設計法則之一—— 好萊塢法則:“別找我們,我們找你”;即由IoC容器幫對象找相應的依賴對象并注入,而不是由對象主動去找。
1.3、IoC和DI
DI—Dependency Injection,即“依賴注入”:組件之間依賴關系由容器在運行期決定,形象的說,即由容器動態的將某個依賴關系注入到組件之中。依賴注入的目的并非為軟件系統帶來更多功能,而是為了提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
理解DI的關鍵是:“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”,那我們來深入分析一下:
●誰依賴于誰:當然是應用程序依賴于IoC容器;
●為什么需要依賴:應用程序需要IoC容器來提供對象需要的外部資源;
●誰注入誰:很明顯是IoC容器注入應用程序某個對象,應用程序依賴的對象;
●注入了什么:就是注入某個對象所需要的外部資源(包括對象、資源、常量數據)。
IoC和DI有什么關系呢?其實它們是同一個概念的不同角度描述,由于控制反轉概念比較含糊(可能只是理解為容器控制對象這一個層面,很難讓人想到誰來維護對象關系),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IoC 而言,“依賴注入”明確描述了“被注入對象依賴IoC容器配置依賴對象”。
看過很多對Spring的Ioc理解的文章,好多人對Ioc和DI的解釋都晦澀難懂,反正就是一種說不清,道不明的感覺,讀完之后依然是一頭霧水,感覺就是開濤這位技術牛人寫得特別通俗易懂,他清楚地解釋了IoC(控制反轉) 和DI(依賴注入)中的每一個字,讀完之后給人一種豁然開朗的感覺。我相信對于初學Spring框架的人對Ioc的理解應該是有很大幫助的。
二、分享Bromon的blog上對IoC與DI淺顯易懂的講解
2.1、IoC(控制反轉)
首先想說說IoC(Inversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC,對于spring框架來說,就是由spring來負責控制對象的生命周期和對象間的關系。這是什么意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪里有長得漂亮身材又好的mm,然后打聽她們的興趣愛好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,然后嘿嘿……這個過程是復雜深奧的,我們必須自己設計和面對每個環節。傳統的程序開發也是如此,在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個,或者從JNDI中查詢一個),使用完之后還要將對象銷毀(比如Connection等),對象始終會和其他的接口或類藕合起來。
那么IoC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什么樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術像齊達內之類的,然后婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結婚就行了。簡單明了,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。Spring所倡導的開發方式就是如此,所有的類都會在spring容器中登記,告訴spring你是個什么東西,你需要什么東西,然后spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創建、銷毀都由 spring來控制,也就是說控制對象生存周期的不再是引用它的對象,而是spring。對于某個具體的對象而言,以前是它控制其他對象,現在是所有對象都被spring控制,所以這叫控制反轉。
2.2、DI(依賴注入)
IoC的一個重點是在系統運行中,動態的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴注入)來實現的。比如對象A需要操作數據庫,以前我們總是要在A中自己編寫代碼來獲得一個Connection對象,有了 spring我們就只需要告訴spring,A中需要一個Connection,至于這個Connection怎么構造,何時構造,A不需要知道。在系統運行時,spring會在適當的時候制造一個Connection,然后像打針一樣,注射到A當中,這樣就完成了對各個對象之間關系的控制。A需要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這么來的。那么DI是如何實現的呢? Java 1.3之后一個重要特征是反射(reflection),它允許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,spring就是通過反射來實現注入的。
理解了IoC和DI的概念后,一切都將變得簡單明了,剩下的工作只是在spring的框架中堆積木而已。
三、對IoC(控制反轉)和DI(依賴注入)的理解
在平時的java應用開發中,我們要實現某一個功能或者說是完成某個業務邏輯時至少需要兩個或以上的對象來協作完成,在沒有使用Spring的時候,每個對象在需要使用他的合作對象時,自己均要使用像new object() 這樣的語法來將合作對象創建出來,這個合作對象是由自己主動創建出來的,創建合作對象的主動權在自己手上,自己需要哪個合作對象,就主動去創建,創建合作對象的主動權和創建時機是由自己把控的,而這樣就會使得對象間的耦合度高了,A對象需要使用合作對象B來共同完成一件事,A要使用B,那么A就對B產生了依賴,也就是A和B之間存在一種耦合關系,并且是緊密耦合在一起,而使用了Spring之后就不一樣了,創建合作對象B的工作是由Spring來做的,Spring創建好B對象,然后存儲到一個容器里面,當A對象需要使用B對象時,Spring就從存放對象的那個容器里面取出A要使用的那個B對象,然后交給A對象使用,至于Spring是如何創建那個對象,以及什么時候創建好對象的,A對象不需要關心這些細節問題(你是什么時候生的,怎么生出來的我可不關心,能幫我干活就行),A得到Spring給我們的對象之后,兩個人一起協作完成要完成的工作即可。
所以控制反轉IoC(Inversion of Control)是說創建對象的控制權進行轉移,以前創建對象的主動權和創建時機是由自己把控的,而現在這種權力轉移到第三方,比如轉移交給了IoC容器,它就是一個專門用來創建對象的工廠,你要什么對象,它就給你什么對象,有了 IoC容器,依賴關系就變了,原先的依賴關系就沒了,它們都依賴IoC容器了,通過IoC容器來建立它們之間的關系。
這是我對Spring的IoC(控制反轉)的理解。DI(依賴注入)其實就是IOC的另外一種說法,DI是由Martin Fowler 在2004年初的一篇論文中首次提出的。他總結:控制的什么被反轉了?就是:獲得依賴對象的方式反轉了。
四、Spring AOP總結
1、簡介
面向切面編程(Aspect Oriented Programming)它與 OOP( Object-Oriented Programming, 面向對象編程) 相輔相成, 提供了與 OOP 不同的抽象軟件結構的視角來思考程序的結構,通過這種方式彌補面向對象編程(Object Oriented Programming)的不足。除了類以外,AOP提供了切面,切面對關注點進行模塊化,例如橫切多個類型和對象的事務管理(這些關注點術語通常稱作橫切(crosscutting)關注點)。Spring AOP是Spring的一個重要組件,但是Spring IOC并不依賴于Spring AOP,這意味著你可以自由選擇是否使用AOP,AOP提供了強大的中間件解決方案,這使得Spring IOC更加完善。我們可以通過AOP來實現日志監聽,事務管理,權限控制等等。
2、概念
-
切面(Aspect):一個關注點的模塊化,這個關注點可能會橫切多個對象。事務管理是J2EE應用中一個關于橫切關注點的很好的例子。在Spring AOP中,切面可以使用基于模式)或者基于@Aspect注解的方式來實現。
-
連接點(Joinpoint):在程序執行過程中某個特定的點,比如某方法調用的時候或者處理異常的時候。在Spring
AOP中,一個連接點總是表示一個方法的執行。 -
通知(Advice):在切面的某個特定的連接點上執行的動作。其中包括了“around”、“before”和“after”等不同類型的通知(通知的類型將在后面部分進行討論)。許多AOP框架(包括Spring)都是以攔截器做通知模型,并維護一個以連接點為中心的攔截器鏈。
-
切入點(Pointcut):匹配連接點的斷言。通知和一個切入點表達式關聯,并在滿足這個切入點的連接點上運行(例如,當執行某個特定名稱的方法時)。切入點表達式如何和連接點匹配是AOP的核心:Spring缺省使用AspectJ切入點語法。
-
引入(Introduction):用來給一個類型聲明額外的方法或屬性(也被稱為連接類型聲明(inter-type
declaration))。Spring允許引入新的接口(以及一個對應的實現)到任何被代理的對象。例如,你可以使用引入來使一個bean實現IsModified接口,以便簡化緩存機制。 -
目標對象(Target Object): 被一個或者多個切面所通知的對象。也被稱做被通知(advised)對象。 既然Spring
AOP是通過運行時代理實現的,這個對象永遠是一個被代理(proxied)對象。 -
AOP代理(AOP Proxy):AOP框架創建的對象,用來實現切面契約(例如通知方法執行等等)。在Spring中,AOP代理可以是JDK動態代理或者CGLIB代理。
-
織入(Weaving):把切面連接到其它的應用程序類型或者對象上,并創建一個被通知的對象。這些可以在編譯時(例如使用AspectJ編譯器),類加載時和運行時完成。Spring和其他純Java AOP框架一樣,在運行時完成織入。
通知類型:
-
前置通知(Before advice):在某連接點之前執行的通知,但這個通知不能阻止連接點之前的執行流程(除非它拋出一個異常)。
-
后置通知(After returning advice):在某連接點正常完成后執行的通知:例如,一個方法沒有拋出任何異常,正常返回。
-
異常通知(After throwing advice):在方法拋出異常退出時執行的通知。
-
最終通知(After (finally) advice):當某連接點退出的時候執行的通知(不論是正常返回還是異常退出)。
-
環繞通知(Around Advice):包圍一個連接點的通知,如方法調用。這是最強大的一種通知類型。環繞通知可以在方法調用前后完成自定義的行為。它也會選擇是否繼續執行連接點或直接返回它自己的返回值或拋出異常來結束執行。
Spring AOP簡單的一個流程圖:
看完了上面的理論部分知識, 我相信還是會有不少朋友感覺到 AOP 的概念還是很模糊, 對 AOP 中的各種概念理解的還不是很透徹. 其實這很正常, 因為 AOP 中的概念是在是太多了, 我當時也是花了老大勁才梳理清楚的.
下面我以一個簡單的例子來比喻一下 AOP 中 Aspect, Joint point, Point cut 與 Advice之間的關系.
讓我們來假設一下, 從前有一個叫爪哇的小縣城, 在一個月黑風高的晚上, 這個縣城中發生了命案. 作案的兇手十分狡猾, 現場沒有留下什么有價值的線索. 不過萬幸的是, 剛從隔壁回來的老王恰好在這時候無意中發現了兇手行兇的過程, 但是由于天色已晚, 加上兇手蒙著面, 老王并沒有看清兇手的面目, 只知道兇手是個男性, 身高約七尺五寸. 爪哇縣的縣令根據老王的描述, 對守門的士兵下命令說: 凡是發現有身高七尺五寸的男性, 都要抓過來審問. 士兵當然不敢違背縣令的命令, 只好把進出城的所有符合條件的人都抓了起來.
來讓我們看一下上面的一個小故事和 AOP 到底有什么對應關系.
首先我們知道, 在 Spring AOP 中 Joint point 指代的是所有方法的執行點, 而 point cut 是一個描述信息, 它修飾的是 Joint point, 通過 point cut, 我們就可以確定哪些 Joint point 可以被織入 Advice. 對應到我們在上面舉的例子, 我們可以做一個簡單的類比, Joint point 就相當于 爪哇的小縣城里的百姓,pointcut 就相當于 老王所做的指控, 即兇手是個男性, 身高約七尺五寸, 而 Advice 則是施加在符合老王所描述的嫌疑人的動作: 抓過來審問.
為什么可以這樣類比呢?
Joint point : 爪哇的小縣城里的百姓: 因為根據定義, Joint point 是所有可能被織入 Advice 的候選的點, 在 Spring AOP中, 則可以認為所有方法執行點都是 Joint point. 而在我們上面的例子中, 命案發生在小縣城中, 按理說在此縣城中的所有人都有可能是嫌疑人.
Pointcut :男性, 身高約七尺五寸: 我們知道, 所有的方法(joint point) 都可以織入 Advice, 但是我們并不希望在所有方法上都織入 Advice, 而 Pointcut 的作用就是提供一組規則來匹配join point, 給滿足規則的 join point 添加 Advice. 同理, 對于縣令來說, 他再昏庸, 也知道不能把縣城中的所有百姓都抓起來審問, 而是根據兇手是個男性, 身高約七尺五寸, 把符合條件的人抓起來. 在這里 兇手是個男性, 身高約七尺五寸 就是一個修飾謂語, 它限定了兇手的范圍, 滿足此修飾規則的百姓都是嫌疑人, 都需要抓起來審問.
Advice :抓過來審問, Advice 是一個動作, 即一段 Java 代碼, 這段 Java 代碼是作用于 point cut 所限定的那些 Joint point 上的. 同理, 對比到我們的例子中, 抓過來審問 這個動作就是對作用于那些滿足 男性, 身高約七尺五寸 的爪哇的小縣城里的百姓.
Aspect::Aspect 是 point cut 與 Advice 的組合, 因此在這里我們就可以類比: “根據老王的線索, 凡是發現有身高七尺五寸的男性, 都要抓過來審問” 這一整個動作可以被認為是一個 Aspect.
總結
以上是生活随笔為你收集整理的Spring IOC/DI和AOP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 1044 access de
- 下一篇: ZBrush 4R8将于6月30停止预售