IOC(控制反轉)和AOP(面向切面編程)是兩種常見(jiàn)的軟件設計原理和機制。
IOC通過(guò)將對象的創(chuàng )建和依賴(lài)關(guān)系的管理交給容器來(lái)實(shí)現,使得對象之間的耦合度降低,提高了代碼的可維護性和可測試性。
AOP通過(guò)將橫切關(guān)注點(diǎn)(如日志、事務(wù)等)從核心業(yè)務(wù)邏輯中分離出來(lái),通過(guò)切面的方式進(jìn)行統一管理,提高了代碼的模塊化和可重用性。
兩者的核心思想都是將關(guān)注點(diǎn)從業(yè)務(wù)邏輯中解耦,提高代碼的可維護性和可擴展性。
IoC(Inversion of Control) (1). IoC(Inversion of Control)是指容器控制程序對象之間的關(guān)系,而不是傳統實(shí)現中,由程序代碼直接操控。控制權由應用代碼中轉到了外部容器,控制權的轉移是所謂反轉。 對于Spring而言,就是由Spring來(lái)控制對象的生命周期和對象之間的關(guān)系;IoC還有另外一個(gè)名字——“依賴(lài)注入(Dependency Injection)”。從名字上理解,所謂依賴(lài)注入,即組件之間的依賴(lài)關(guān)系由容器在運行期決定,即由容器動(dòng)態(tài)地將某種依賴(lài)關(guān)系注入到組件之中。 (2). 在Spring的工作方式中,所有的類(lèi)都會(huì )在spring容器中登記,告訴spring這是個(gè)什么東西,你需要什么東西,然后spring會(huì )在系統運行到適當的時(shí)候,把你要的東西主動(dòng)給你,同時(shí)也把你交給其他需要你的東西。所有的類(lèi)的創(chuàng )建、銷(xiāo)毀都由 spring來(lái)控制,也就是說(shuō)控制對象生存周期的不再是引用它的對象,而是spring。對于某個(gè)具體的對象而言,以前是它控制其他對象,現在是所有對象都被spring控制,所以這叫控制反轉。(3). 在系統運行中,動(dòng)態(tài)的向某個(gè)對象提供它所需要的其他對象。 (4). 依賴(lài)注入的思想是通過(guò)反射機制實(shí)現的,在實(shí)例化一個(gè)類(lèi)時(shí),它通過(guò)反射調用類(lèi)中set方法將事先保存在HashMap中的類(lèi)屬性注入到類(lèi)中。 總而言之,在傳統的對象創(chuàng )建方式中,通常由調用者來(lái)創(chuàng )建被調用者的實(shí)例,而在Spring中創(chuàng )建被調用者的工作由Spring來(lái)完成,然后注入調用者,即所謂的依賴(lài)注入or控制反轉。 注入方式有兩種:依賴(lài)注入和設置注入; IoC的優(yōu)點(diǎn):降低了組件之間的耦合,降低了業(yè)務(wù)對象之間替換的復雜性,使之能夠靈活的管理對象。AOP(Aspect Oriented Programming)(1). AOP面向方面編程基于IoC,是對OOP的有益補充;(2). AOP利用一種稱(chēng)為“橫切”的技術(shù),剖解開(kāi)封裝的對象內部,并將那些影響了 多個(gè)類(lèi)的公共行為封裝到一個(gè)可重用模塊,并將其名為“Aspect”,即方面。所謂“方面”,簡(jiǎn)單地說(shuō),就是將那些與業(yè)務(wù)無(wú)關(guān),卻為業(yè)務(wù)模塊所共同調用的 邏輯或責任封裝起來(lái),比如日志記錄,便于減少系統的重復代碼,降低模塊間的耦合度,并有利于未來(lái)的可操作性和可維護性。(3). AOP代表的是一個(gè)橫向的關(guān) 系,將“對象”比作一個(gè)空心的圓柱體,其中封裝的是對象的屬性和行為;則面向方面編程的方法,就是將這個(gè)圓柱體以切面形式剖開(kāi),選擇性的提供業(yè)務(wù)邏輯。而 剖開(kāi)的切面,也就是所謂的“方面”了。然后它又以巧奪天功的妙手將這些剖開(kāi)的切面復原,不留痕跡,但完成了效果。(4). 實(shí)現AOP的技術(shù),主要分為兩大類(lèi):一是采用動(dòng)態(tài)代理技術(shù),利用截取消息的方式,對該消息進(jìn)行裝飾,以取代原有對象行為的執行;二是采用靜態(tài)織入的方式,引入特定的語(yǔ)法創(chuàng )建“方面”,從而使得編譯器可以在編譯期間織入有關(guān)“方面”的代碼。(5). Spring實(shí)現AOP:JDK動(dòng)態(tài)代理和CGLIB代理 JDK動(dòng)態(tài)代理:其代理對象必須是某個(gè)接口的實(shí)現,它是通過(guò)在運行期間創(chuàng )建一個(gè)接口的實(shí)現類(lèi)來(lái)完成對目標對象的代理;其核心的兩個(gè)類(lèi)是InvocationHandler和Proxy。 CGLIB代理:實(shí)現原理類(lèi)似于JDK動(dòng)態(tài)代理,只是它在運行期間生成的代理對象是針對目標類(lèi)擴展的子類(lèi)。CGLIB是高效的代碼生成包,底層是依靠ASM(開(kāi)源的java字節碼編輯類(lèi)庫)操作字節碼實(shí)現的,性能比JDK強;需要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ注解驅動(dòng)的切面實(shí)際上底層也是通過(guò)動(dòng)態(tài)代理實(shí)現的。(6). AOP使用場(chǎng)景: Authentication 權限檢查 Caching 緩存 Context passing 內容傳遞 Error handling 錯誤處理 Lazy loading 延遲加載 Debugging 調試 logging, tracing, profiling and monitoring 日志記錄,跟蹤,優(yōu)化,校準 Performance optimization 性能優(yōu)化,效率檢查 Persistence 持久化 Resource pooling 資源池 Synchronization 同步 Transactions 事務(wù)管理 另外Filter的實(shí)現和struts2的攔截器的實(shí)現都是AOP思想的體現。 我們是在使用Spring框架的過(guò)程中,其實(shí)就是為了使用IOC,依賴(lài)注入,和AOP,面向切面編程,這兩個(gè)是Spring的靈魂。主要用到的設計模式有工廠(chǎng)模式和代理模式。IOC就是典型的工廠(chǎng)模式,通過(guò)sessionfactory去注入實(shí)例。AOP就是典型的代理模式的體現。代理模式是常用的java設計模式,他的特征是代理類(lèi)與委托類(lèi)有同樣的接口,代理類(lèi)主要負責為委托類(lèi)預處理消息、過(guò)濾消息、把消息轉發(fā)給委托類(lèi),以及事后處理消息等。代理類(lèi)與委托類(lèi)之間通常會(huì )存在關(guān)聯(lián)關(guān)系,一個(gè)代理類(lèi)的對象與一個(gè)委托類(lèi)的對象關(guān)聯(lián),代理類(lèi)的對象本身并不真正實(shí)現服務(wù),而是通過(guò)調用委托類(lèi)的對象的相關(guān)方法,來(lái)提供特定的服務(wù)。 spring的IoC容器是spring的核心,spring AOP是spring框架的重要組成部分。在傳統的程序設計中,當調用者需要被調用者的協(xié)助時(shí),通常由調用者來(lái)創(chuàng )建被調用者的實(shí)例。但在spring里創(chuàng )建被調用者的工作不再由調用者來(lái)完成,因此控制反轉(IoC);創(chuàng )建被調用者實(shí)例的工作通常由spring容器來(lái)完成,然后注入調用者,因此也被稱(chēng)為依賴(lài)注入(DI),依賴(lài)注入和控制反轉是同一個(gè)概念。面向方面編程(AOP)是以另一個(gè)角度來(lái)考慮程序結構,通過(guò)分析程序結構的關(guān)注點(diǎn)來(lái)完善面向對象編程(OOP)。OOP將應用程序分解成各個(gè)層次的對象,而AOP將程序分解成多個(gè)切面。spring AOP 只實(shí)現了方法級別的連接點(diǎn),在J2EE應用中,AOP攔截到方法級別的操作就已經(jīng)足夠。在spring中,未來(lái)使IoC方便地使用健壯、靈活的企業(yè)服務(wù),需要利用spring AOP實(shí)現為IoC和企業(yè)服務(wù)之間建立聯(lián)系。
IOC:控制反轉也叫依賴(lài)注入。利用了工廠(chǎng)模式將對象交給容器管理,你只需要在spring配置文件總配置相應的bean,以及設置相關(guān)的屬性,讓spring容器來(lái)生成類(lèi)的實(shí)例對象以及管理對象。在spring容器啟動(dòng)的時(shí)候,spring會(huì )把你在配置文件中配置的bean都初始化好,然后在你需要調用的時(shí)候,就把它已經(jīng)初始化好的那些bean分配給你需要調用這些bean的類(lèi)(假設這個(gè)類(lèi)名是A),分配的方法就是調用A的setter方法來(lái)注入,而不需要你在A(yíng)里面new這些bean了。注意:面試的時(shí)候,如果有條件,畫(huà)圖,這樣更加顯得你懂了.
AOP:面向切面編程。(Aspect-Oriented Programming)AOP可以說(shuō)是對OOP的補充和完善。OOP引入封裝、繼承和多態(tài)性等概念來(lái)建立一種對象層次結構,用以模擬公共行為的一個(gè)集合。當我們需要為分散的對象引入公共行為的時(shí)候,OOP則顯得無(wú)能為力。也就是說(shuō),OOP允許你定義從上到下的關(guān)系,但并不適合定義從左到右的關(guān)系。例如日志功能。日志代碼往往水平地散布在所有對象層次中,而與它所散布到的對象的核心功能毫無(wú)關(guān)系。在OOP設計中,它導致了大量代碼的重復,而不利于各個(gè)模塊的重用。將程序中的交叉業(yè)務(wù)邏輯(比如安全,日志,事務(wù)等),封裝成一個(gè)切面,然后注入到目標對象(具體業(yè)務(wù)邏輯)中去。實(shí)現AOP的技術(shù),主要分為兩大類(lèi):一是采用動(dòng)態(tài)代理技術(shù),利用截取消息的方式,對該消息進(jìn)行裝飾,以取代原有對象行為的執行;二是采用靜態(tài)織入的方式,引入特定的語(yǔ)法創(chuàng )建“方面”,從而使得編譯器可以在編譯期間織入有關(guān)“方面”的代碼.簡(jiǎn)單點(diǎn)解釋?zhuān)确秸f(shuō)你想在你的biz層所有類(lèi)中都加上一個(gè)打印‘你好’的功能,這時(shí)就可以用aop思想來(lái)做.你先寫(xiě)個(gè)類(lèi)寫(xiě)個(gè)類(lèi)方法,方法經(jīng)實(shí)現打印‘你好’,然后Ioc這個(gè)類(lèi) ref=“biz.*”讓每個(gè)類(lèi)都注入即可實(shí)現。