1. 程式人生 > >切面程式設計要點研究

切面程式設計要點研究

術語:
切面(aspect): 橫切面物件,一般為一個具體類物件(可以藉助@Aspect宣告),用於封裝擴充套件業務的一個類的物件。
連線點(joinpoint):程式執行過程中某個特定的點,一般指被攔截到的的方法
切入點(pointcut):對連線點攔截內容的一種定義,一般可以理解為多個連線點的結合.
通知(Advice):在切面的某個特定連線點上執行的動作(擴充套件功能),例如around,before,after等,切面擴充套件業務中的一個操作(方法)。
底層:
1)假如目標物件(被代理物件)實現介面,則底層預設採用JDK動態代理機制為目標物件建立代理物件(目標類和代理類會實現共同介面)
2)假如目標物件(被代理物件)沒有實現介面,則底層預設採用CGLIB代理機制為目標物件建立代理物件(預設建立的代理類會繼承目標物件型別)。
切面程式設計原則:


AOP就是要在基於OCP(開閉原則)在不改變原有系統核心業務程式碼的基礎上動態新增一些擴充套件功能並可以控制物件的執行。
註解:
@Aspect 註解用於標識此類為一個AOP橫切面物件
@Pointcut 註解用於定義本類中的切入點。
@Before 用於定義一個前置通知(滿足切入點表示式的核心業務方法執行之前要執行的一個操作)
@After 用於定義一個後置通知(滿足切入點表示式的核心業務方法執行之後要執行的一個操作)
@Order(1)定義優先順序,數字越小優先順序越高,先執行
@annotaion應用於方法級別,實現細粒度的控制
五種通知:
1)前置通知 (@Before) 方法執行之前執行
2)返回通知 (@AfterReturning) 方法return之後執行
3)異常通知 (@AfterThrowing) 方法出現異常之後執行
4)後置通知 (@After) : 又稱之為最終通知(finally)
5)環繞通知 (@Around) :可以擷取方法,在方法之中增加程式碼
環繞通知註解切面程式設計的使用:

1.通過註解進行切面物件的注入
如下所示,表示將使用者實現類交給環繞通知,AOP會對此實現類進行監聽,當執行此實現類的方法時,會直接被攔截轉而執行註解的方法。

@Around(“bean(sysUserServiceImpl)”)
public Object aroundMethod (ProceedingJoinPoint joinPoint) throws Throwable {
}

2.可以通過註解的ProceedingJoinPoint引數獲取注入物件的類物件,進而獲取其詳細資訊
3.當呼叫注入類的方法時
joinPoint.getTarget().getClass()獲取環繞通知對應的類
joinPoint.getSignature().getName()獲取呼叫方法的方法名
joinPoint.getArgs()獲取呼叫方法的引數
ShiroUtils.getPrincipal().getUsername()這是shiro框架的工具類,用於獲取登入使用者的使用者名稱
環繞通知XML切面程式設計的使用:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 使用xml的方式配置aop功能 -->
    <!-- ①將需要新增切面(例如日誌)的bean註冊到IoC中 -->
    <bean id="calculator" class="com.wlg.cal.Calculator"></bean>
    <!-- ②將切面類註冊到IoC中 -->
    <bean id="logAspect" class="com.wlg.aspect.LogAspect"></bean>
    <!-- ③配置切面類切入位置和切入點,需要使用AOP名稱空間 -->
    <aop:config>
        <!-- 設定一個通用切入點表示式 -->
        <aop:pointcut expression="execution(* * .*(..))" id="mypoint"/>
        <aop:aspect id="lA" ref="logAspect">
            <aop:before method="calStart" pointcut-ref="mypoint"/>
            <aop:after method="calEnd" pointcut-ref="mypoint"/>
            <aop:after-returning method="calReturn" pointcut-ref="mypoint" returning="rt"/>
            <aop:after-throwing method="calException" pointcut-ref="mypoint" throwing="e"/>
        </aop:aspect>
        <!-- 當有多個切面類的時候,就多用幾個aop:aspect標籤 -->
    </aop:config>
</beans>

切入點表示式形式:
切入點表示式:
語法:execution(方法的完整簽名)
execution(訪問控制符 返回值 全類名.方法名(引數型別表))
:用來通配除過引數列表外的東西,訪問控制符不用通配,忽略訪問控制符,就是表示所有的控制符都可以
…:表示所有型別,任意多個引數
在這裡插入圖片描述