Java中的面向切面編程(AOP)

1、什麼是AOP?

Aspect Oriented Programming ,即面向切面編程java

  • AOP是對面向對象編程的一個補充。
  • 它的目的是將複雜的需求分解爲不一樣的切面,將散佈在系統中的公共功能集中解決。
  • 它的實際含義是在運行時將代碼切入到類的指定方法、指定位置上,將不一樣方法的同一個位置抽象爲一個切面對象,並對該對象進行編程。

下面是AOP的一個示意圖
AOP示意圖spring

2、AOP的優勢和一些概念

一、AOP的優勢
  • 下降模塊之間的耦合度
  • 使系統更容易擴展
  • 更好的代碼複用
  • 非業務代碼更加集中,不分散,便於統一管理
  • 業務代碼更加簡潔純粹,不摻雜其餘的代碼的影響
二、AOP中出現的一些概念
  • 切面:橫切關注點,被模塊化的抽象對象
  • 通知:切面對象完成的工做(非業務代碼)
  • 目標:被通知的對象(即被橫切的對象)
  • 代理:切面、通知、目標混合以後的對象
  • 鏈接點:通知要插入業務代碼的具體位置(如Spring實現中的JoinPoint)
  • 切點:AOP經過切點定位到鏈接點

3、使用動態代理實現AOP

一、添加依賴
<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>
二、建立一個計算器接口Cal,定義四個方法

動態代理的類的方法應當都由接口來實現,這樣才方便使用動態代理對象執行方法
計算器接口Cal編程

三、建立接口的實現類CalImpl

高耦合的寫法,每次打印日誌都要手動完成:
高耦合的寫法框架

四、使用動態代理進行優化

上方代碼中,日誌信息和業務邏輯的耦合性很高,不利於代碼的維護。使用AOP能夠進行優化,咱們可使用動態代理實現AOP:
給業務代碼找一個代理,打印日誌信息的工做交給代理來作。這樣的話業務代碼就只須要關注自身業務便可。
(1)去掉手動輸出的日誌信息
去掉手動輸出的日誌信息
(2).代理輔助類的編寫和使用(動態代理的核心)模塊化

咱們建立的並非所謂的代理類,而是一個能夠幫助咱們返回代理對象的輔助類,這個輔助類有兩個功能測試

  1. 接收委託對象並依次返回代理對象
  2. 處理代理對象調用方法的過程
    建立代理輔助類
    值得注意的是:
  • 注意別忘了給委託對象賦值的那一步
  • 建立代理動態代理對象時傳入的方法保證了代理類擁有原類的所有功能
  • 調用代理對象的方法時會自動調用invoke方法
    (3)測試
    測試動態代理實現AOP

4、使用Spring實現AOP

動態代理實現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>
二、建立一個計算器接口Cal,定義四個方法

當使用Spring實現時,這一步非必須!直接在實體類裏面定義方法也可
計算器接口3d

三、定義實體類,實現方法

注意須要加上Component註解把他交給IoC
定義實體類,實現方法代理

四、建立切面類

建立切面類
類定義處的兩個註解日誌

  • @Aspect表示該類是一個切面類
  • @Component將該類的對象注入到IoC容器(切面類和實體類都須要加上這個註解)

方法處的註解

  • @Before表示方法執行的具體位置和時機是方法開始時

  • @After相似Before,不過位置是方法的最後
    在這裏插入圖片描述

  • @AfterReturning在下文有做解釋

  • @AfterThrowing在下文有做解釋

五、在spring.xml中進行配置

Spring配置文件

  • context:component-scan指掃描com.pedro包中的全部類,若是該類同時添加了component註解,則將該類掃描IoC容器中。即IoC管理它的對象
  • aop:aspectj-autoproxy讓Spring容器結合切面類和目標類自動生成代理對象
六、使用

使用Spring的AOP
用代理對象調用方法就會自動執行它自己的方法和切面類中的非業務代碼

爲何類名首字母要小寫?
當使用註解配置bean時,默認id(別名)就是首字母改成小寫的類名。若想修改,就在實體類的註解處加上自定義的名字便可。如@Component("test"),這樣的話在getBean的時候就可使用自定義的別名了,即xx.getBean("test")

七、兩個特殊的After註解

(1)AfterReturning

用於在獲取返回值後執行一段非業務代碼
AfterReturning

注:由於有兩個參數,這裏的value標籤名被標出,而上面的before、after等註解只有一個參數,因此省略了value

結合上面的其餘註解,會輸出:

div方法的參數是[6,2]
div方法執行完畢
div方法的結果是3

(2)AfterThrowing

切面類的AfterThrowing註解,用於在拋出異常後執行一段非業務代碼
AfterThrowing
結合上面的其餘註解,會輸出:

div方法的參數是[6,0]
div方法執行完畢
div方法拋出的異常:java.lang.ArithmeticException: / by zero

2021.4.3

相關文章
相關標籤/搜索