
Java中的面向切面程式設計(AOP)
Aspect Oriented Programming ,即面向切面程式設計。
AOP是對面向對象程式設計的一個補充。
它的目的是将複雜的需求分解為不同的切面,将散布在系統中的公共功能集中解決。
它的實際含義是在運作時将代碼切入到類的指定方法、指定位置上,将不同方法的同一個位置抽象為一個切面對象,并對該對象進行程式設計。
下面是AOP的一個示意圖
降低子產品之間的耦合度
使系統更容易擴充
更好的代碼複用
非業務代碼更加集中,不分散,便于統一管理
業務代碼更加簡潔純粹,不摻雜其他的代碼的影響
切面:橫切關注點,被子產品化的抽象對象
通知:切面對象完成的工作(非業務代碼)
目标:被通知的對象(即被橫切的對象)
代理:切面、通知、目标混合之後的對象
連接配接點:通知要插入業務代碼的具體位置(如Spring實作中的JoinPoint)
切點:AOP通過切點定位到連接配接點
動态代理的類的方法應當都由接口來實作,這樣才友善使用動态代理對象執行方法
高耦合的寫法,每次列印日志都要手動完成:
上方代碼中,日志資訊和業務邏輯的耦合性很高,不利于代碼的維護。使用AOP可以進行優化,我們可以使用動态代理實作AOP:
給業務代碼找一個代理,列印日志資訊的工作交給代理來做。這樣的話業務代碼就隻需要關注自身業務即可。
(1)去掉手動輸出的日志資訊
(2).代理輔助類的編寫和使用(動态代理的核心)
我們建立的并不是所謂的代理類,而是一個可以幫助我們傳回代理對象的輔助類,這個輔助類有兩個功能
接收委托對象并依次傳回代理對象
處理代理對象調用方法的過程
值得注意的是:
注意别忘了給委托對象指派的那一步
建立代理動态代理對象時傳入的方法保證了代理類擁有原類的全部功能
調用代理對象的方法時會自動調用invoke方法
(3)測試
動态代理實作AOP比較複雜,不易了解。Spring架構對AOP進行了封裝,使用Spring架構可以用面向對象的思想實作AOP。Spring架構中不需要建立輔助類,隻需要建立一個切面對象,将所有的非業務代碼在切面對象中完成即可(但實際上Spring架構底層依然會根據切面類和代理類來生成代理對象。)
當使用Spring實作時,這一步非必須!直接在實體類裡面定義方法也可
注意需要加上Component注解把他交給IoC
類定義處的兩個注解
<code>@Aspect</code>表示該類是一個切面類
<code>@Component</code>将該類的對象注入到IoC容器(切面類和實體類都需要加上這個注解)
方法處的注解
<code>@Before</code>表示方法執行的具體位置和時機是方法開始時
<code>@After</code>類似Before,不過位置是方法的最後
<code>@AfterReturning</code>在下文有作解釋
<code>@AfterThrowing</code>在下文有作解釋
<code>context:component-scan</code>指掃描com.pedro包中的所有類,如果該類同時添加了component注解,則将該類掃描IoC容器中。即IoC管理它的對象
<code>aop:aspectj-autoproxy</code>讓Spring容器結合切面類和目标類自動生成代理對象
用代理對象調用方法就會自動執行它本身的方法和切面類中的非業務代碼
為什麼類名首字母要小寫?
當使用注解配置bean時,預設id(别名)就是首字母改為小寫的類名。若想修改,就在實體類的注解處加上自定義的名字即可。如<code>@Component("test")</code>,這樣的話在getBean的時候就可以使用自定義的别名了,即<code>xx.getBean("test")</code>
(1)AfterReturning
用于在擷取傳回值後執行一段非業務代碼
注:因為有兩個參數,這裡的value标簽名被标出,而上面的before、after等注解隻有一個參數,是以省略了value
結合上面的其他注解,會輸出:
(2)AfterThrowing
切面類的AfterThrowing注解,用于在抛出異常後執行一段非業務代碼
2021.4.3