Aspect Oriented Programming ,即面向切面編程。java
下面是AOP的一個示意圖
spring
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.11.RELEASE</version> </dependency>
動態代理的類的方法應當都由接口來實現,這樣才方便使用動態代理對象執行方法
編程
高耦合的寫法,每次打印日誌都要手動完成:
框架
上方代碼中,日誌信息和業務邏輯的耦合性很高,不利於代碼的維護。使用AOP能夠進行優化,咱們可使用動態代理實現AOP:
給業務代碼找一個代理,打印日誌信息的工做交給代理來作。這樣的話業務代碼就只須要關注自身業務便可。
(1)去掉手動輸出的日誌信息
(2).代理輔助類的編寫和使用(動態代理的核心)模塊化
咱們建立的並非所謂的代理類,而是一個能夠幫助咱們返回代理對象的輔助類,這個輔助類有兩個功能測試
動態代理實現AOP比較複雜,不易理解。Spring框架對AOP進行了封裝,使用Spring框架能夠用面向對象的思想實現AOP。Spring框架中不須要建立輔助類,只須要建立一個切面對象,將全部的非業務代碼在切面對象中完成便可(但實際上Spring框架底層依然會根據切面類和代理類來生成代理對象。)優化
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.11.RELEASE</version> </dependency>
當使用Spring實現時,這一步非必須!直接在實體類裏面定義方法也可
3d
注意須要加上Component註解把他交給IoC
代理
類定義處的兩個註解日誌
@Aspect
表示該類是一個切面類@Component
將該類的對象注入到IoC容器(切面類和實體類都須要加上這個註解)方法處的註解
@Before
表示方法執行的具體位置和時機是方法開始時
@After
相似Before,不過位置是方法的最後
@AfterReturning
在下文有做解釋
@AfterThrowing
在下文有做解釋
context:component-scan
指掃描com.pedro包中的全部類,若是該類同時添加了component註解,則將該類掃描IoC容器中。即IoC管理它的對象aop:aspectj-autoproxy
讓Spring容器結合切面類和目標類自動生成代理對象
用代理對象調用方法就會自動執行它自己的方法和切面類中的非業務代碼
爲何類名首字母要小寫?
當使用註解配置bean時,默認id(別名)就是首字母改成小寫的類名。若想修改,就在實體類的註解處加上自定義的名字便可。如@Component("test")
,這樣的話在getBean的時候就可使用自定義的別名了,即xx.getBean("test")
(1)AfterReturning
用於在獲取返回值後執行一段非業務代碼
注:由於有兩個參數,這裏的value標籤名被標出,而上面的before、after等註解只有一個參數,因此省略了value
結合上面的其餘註解,會輸出:
div方法的參數是[6,2] div方法執行完畢 div方法的結果是3
(2)AfterThrowing
切面類的AfterThrowing註解,用於在拋出異常後執行一段非業務代碼
結合上面的其餘註解,會輸出:
div方法的參數是[6,0] div方法執行完畢 div方法拋出的異常:java.lang.ArithmeticException: / by zero
2021.4.3