qt 記錄一個qt串列埠獲取指定格式加密報文的一個函式
1.3)AOP概念
-
AOP(Aspect Oriented Programing)面向切面程式設計,一種程式設計正規化,隸屬於軟工範疇,指導開發者如何組織程式結構
-
AOP彌補了OOP的不足,基於OOP基礎之上進行橫向開發
-
uOOP規定程式開發以類為主體模型,一切圍繞物件進行,完成某個任務先構建模型
-
uAOP程式開發主要關注基於OOP開發中的共性功能,一切圍繞共性功能進行,完成某個任務先構建可能遇到的所有共性功能(當所有功能都開發出來也就沒有共性與非共性之分)
-
-
“AOP聯盟”
1.4)AOP作用
-
伴隨著AOP時代的降臨,可以從各個行業的標準化、規範化開始入手,一步一步將所有共性功能逐一開發完畢,最終以功能組合來完成個別業務模組乃至整體業務系統的開發
-
目標:將軟體開發由手工製作走向半自動化/全自動化階段,實現“插拔式元件體系結構”搭建
1.5)AOP優勢
-
提高程式碼的可重用性
-
業務程式碼編碼更簡潔
-
業務程式碼維護更高效
-
業務功能擴充套件更便捷
2)AOP入門案例
-
Joinpoint(連線點):就是方法
-
Pointcut(切入點):就是挖掉共性功能的方法
-
Advice(通知):就是共性功能,最終以一個方法的形式呈現
-
Aspect(切面):就是共性功能與挖的位置的對應關係
-
Target(目標物件):就是挖掉功能的方法對應的類產生的物件,這種物件是無法直接完成最終工作的
-
Weaving(織入):就是將挖掉的功能回填的動態過程
-
Proxy(代理):目標物件無法直接完成工作,需要對其進行功能回填,通過建立原始物件的代理物件實現
-
Introduction(引入/引介) :就是對原始物件無中生有的新增成員變數或成員方法
2.2)AOP開發過程
-
開發階段(開發者完成)
-
正常的製作程式
-
將非共性功能開發到對應的目標物件類中,並製作成切入點方法
-
將共性功能獨立開發出來,製作成通知
-
在配置檔案中,宣告切入點
-
在配置檔案中,宣告切入點與通知間的關係(含通知型別),即切面
-
-
執行階段(AOP完成)
-
Spring容器載入配置檔案,監控所有配置的切入點方法的執行
-
當監控到切入點方法被執行,使用代理
-
2.2)AOP開發步驟
-
引入相關包
-
引入配置檔案
<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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --> </beans>
-
編寫目標類並配置:
@Service("userService")
public class UserServiceImpl implements UserService {
public void findAll(){
System.out.println("findAll .... ....");
}
public int save(int i,int m){
System.out.println("user service running..."+i+","+m);
return 100;
}
}
<bean id="UserService" class="demo1.UserServiceImpl"></bean>
- 編寫切面類,假設用於許可權驗證並配置
public class AOPAdvice {
public void checkPri(){
System.out.println("check auth");
}
}
<bean id="myAdvice" class="demo1.AOPAdvice"></bean>
- 通過AOP配置完成對目標類的增強
<aop:config>
<aop:pointcut expression="execution(* demo1.UserServiceImpl.find*(..))" id="pt1"/>
<aop:aspect ref="myAdvice">
<aop:before method="chechPri" pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
3)切入點表示式
3.1)切入點表示式的組成
-
切入點描述的是某個方法
-
切入點表示式是一個快速匹配方法描述的通配格式,類似於正則表示式
關鍵字(訪問修飾符 返回值 包名.類名.方法名(引數)異常名)
關鍵字:描述表示式的匹配模式(參看關鍵字列表)
訪問修飾符:方法的訪問控制權限修飾符
類名:方法所在的類(此處可以配置介面名稱)
異常:方法定義中指定丟擲的異常
-
範例:
execution(public User xxx.xxx.service.UserServiceImpl.find(..))
3.2)切入點表示式——關鍵字
-
execution :匹配執行指定方法
-
args :匹配帶有指定引數型別的方法
-
within :……
-
this :……
-
target :……
-
@within :……
-
@target :……
-
@args :……
-
@annotation :……
-
bean :……
-
reference pointcut :……
3.3)切入點表示式——萬用字元
-
*:單個獨立的任意符號,可以獨立出現,也可以作為字首或者字尾的匹配符出現
execution(public * com.baidu.*.UserServiceImpl.find*(*))
匹配com.baidu包下的任意包中的UserService類或介面中所有find開頭的帶有一個引數的方法
-
.. :多個連續的任意符號,可以獨立出現,常用於簡化包名與引數的書寫
execution(public User com..UserServiceImpl.findById(..))
匹配com包下的任意包中的UserService類或介面中所有名稱為findById的方法
-
+:專用於匹配子類型別
execution(* *..*Service+.*(..))
3.4)切入點表示式——邏輯運算子
-
&& :連線兩個切入點表示式,表示兩個切入點表示式同時成立的匹配
-
|| :連線兩個切入點表示式,表示兩個切入點表示式成立任意一個的匹配
-
! :連線單個切入點表示式,表示該切入點表示式不成立的匹配
3.5)切入點的三種配置方式
<aop:config>
<!--配置公共切入點-->
<aop:pointcut id="pt1" expression="execution(* *(..))"/>
<aop:aspect ref="myAdvice">
<!--配置區域性切入點-->
<aop:pointcut id="pt2" expression="execution(* *(..))"/>
<!--引用公共切入點-->
<aop:before method="logAdvice" pointcut-ref="pt1"/>
<!--引用區域性切入點-->
<aop:before method="logAdvice" pointcut-ref="pt2"/>
<!--直接配置切入點-->
<aop:before method="logAdvice" pointcut="execution(* *(..))"/>
</aop:aspect>
</aop:config>
3.6)切入點配置經驗
-
企業開發命名規範嚴格遵循規範文件進行
-
先為方法配置區域性切入點
-
再抽取類中公共切入點
-
最後抽取全域性切入點
-
程式碼走查過程中檢測切入點是否存在越界性包含
-
程式碼走查過程中檢測切入點是否存在非包含性進駐
-
設定AOP執行檢測程式,在單元測試中監控通知被執行次數與預計次數是否匹配
-
設定完畢的切入點如果發生調整務必進行迴歸測試
(以上規則適用於XML配置格式)
3.7)通知型別
AOP的通知型別共5種
-
前置通知:原始方法執行前執行,如果通知中丟擲異常,阻止原始方法執行
應用:資料校驗
-
後置通知:原始方法執行後執行,無論原始方法中是否出現異常,都將執行通知
應用:現場清理
-
返回後通知:原始方法正常執行完畢並返回結果後執行,如果原始方法中丟擲異常,無法執行
應用:返回值相關資料處理
-
丟擲異常後通知:原始方法丟擲異常後執行,如果原始方法沒有丟擲異常,無法執行
應用:對原始方法中出現的異常資訊進行處理
-
環繞通知:在原始方法執行前後均有對應執行執行,還可以阻止原始方法的執行
應用:十分強大,可以做任何事情
3.7.1)aop:before
-
名稱:aop:before
-
型別:標籤
-
歸屬:aop:aspect標籤
-
作用:設定前置通知
-
格式:
<aop:aspect ref="myAdvice"> <aop:before method="methodName" pointcut="……"/> </aop:aspect>
-
說明:一個aop:aspect標籤中可以配置多個aop:before標籤
-
基本屬性:
-
method :在通知類中設定當前通知類別對應的方法
-
pointcut :設定當前通知對應的切入點表示式,與pointcut-ref屬性衝突
-
pointcut-ref :設定當前通知對應的切入點id,與pointcut屬性衝突
-
3.7.2)aop:after
-
名稱:aop:after
-
型別:標籤
-
歸屬:aop:aspect標籤
-
作用:設定後置通知
-
格式:
<aop:aspect ref="myAdvice"> <aop:after method="methodName" pointcut="……"/> </aop:aspect>
-
說明:一個aop:aspect標籤中可以配置多個aop:after標籤
-
基本屬性:
-
method :在通知類中設定當前通知類別對應的方法
-
pointcut :設定當前通知對應的切入點表示式,與pointcut-ref屬性衝突
-
pointcut-ref :設定當前通知對應的切入點id,與pointcut屬性衝突
-
3.7.3)aop:after-returning
-
名稱:aop:after-returning
-
型別:標籤
-
歸屬:aop:aspect標籤
-
作用:設定返回後通知
-
格式:
<aop:aspect ref="myAdvice"> <aop:after-returning method="methodName" pointcut="……"/> </aop:aspect>
-
說明:一個aop:aspect標籤中可以配置多個aop:after-returning標籤
-
基本屬性:
-
method :在通知類中設定當前通知類別對應的方法
-
pointcut :設定當前通知對應的切入點表示式,與pointcut-ref屬性衝突
-
pointcut-ref :設定當前通知對應的切入點id,與pointcut屬性衝突
-
3.7.4)aop:after-throwing
-
名稱:aop:after-throwing
-
型別:標籤
-
歸屬:aop:aspect標籤
-
作用:設定丟擲異常後通知
-
格式:
<aop:aspect ref="myAdvice"> <aop:after-throwing method="methodName" pointcut="……"/> </aop:aspect>
-
說明:一個aop:aspect標籤中可以配置多個aop:after-throwing標籤
-
基本屬性:
-
method :在通知類中設定當前通知類別對應的方法
-
pointcut :設定當前通知對應的切入點表示式,與pointcut-ref屬性衝突
-
pointcut-ref :設定當前通知對應的切入點id,與pointcut屬性衝突
-
3.7.5)aop:around
-
名稱:aop:around
-
型別:標籤
-
歸屬:aop:aspect標籤
-
作用:設定環繞通知
-
格式:
<aop:aspect ref="myAdvice"> <aop:around method="methodName" pointcut="……"/> </aop:aspect>
-
說明:一個aop:aspect標籤中可以配置多個aop:around標籤
-
基本屬性:
-
method :在通知類中設定當前通知類別對應的方法
-
pointcut :設定當前通知對應的切入點表示式,與pointcut-ref屬性衝突
-
pointcut-ref :設定當前通知對應的切入點id,與pointcut屬性衝突
-
環繞通知的開發方式
-
環繞通知是在原始方法的前後新增功能,在環繞通知中,存在對原始方法的顯式呼叫
public Object around(ProceedingJoinPoint pjp) throws Throwable { Object ret = pjp.proceed(); return ret; }
-
環繞通知方法相關說明:
-
方法須設定Object型別的返回值,否則會攔截原始方法的返回。如果原始方法返回值型別為void,通知方 也可以設定返回值型別為void,最終返回null
-
方法需在第一個引數位置設定ProceedingJoinPoint物件,通過該物件呼叫proceed()方法,實現對原始方法的呼叫。如省略該引數,原始方法將無法執行
-
使用proceed()方法呼叫原始方法時,因無法預知原始方法執行過程中是否會出現異常,強制丟擲Throwable物件,封裝原始方法中可能出現的異常資訊
-
3.8)通知順序(瞭解)
當同一個切入點配置了多個通知時,通知會存在執行的先後順序,該順序以通知配置的順序為準
3.9)通知獲取資料
-
引數
-
返回值
-
異常
3.9.1)通知獲取引數資料
第一種情況:
-
設定通知方法第一個引數為JoinPoint,通過該物件呼叫getArgs()方法,獲取原始方法執行的引數陣列
public void before(JoinPoint jp) throws Throwable { Object[] args = jp.getArgs(); }
-
所有的通知均可以獲取引數
第二種情況:
-
設定切入點表示式為通知方法傳遞引數(鎖定通知變數名)
-
原始方法
第三種情況
-
設定切入點表示式為通知方法傳遞引數(改變通知變數名的定義順序)
-
原始方法
3.9.2)通知獲取返回值資料
第一種:返回值變數名
-
設定返回值變數名
-
原始方法
public int save() { System.out.println("user service running..."); return 100; }
-
AOP配置
<aop:aspect ref="myAdvice"> <aop:pointcut id="pt3" expression="execution(* *(..)) "/> <aop:after-returning method="afterReturning" pointcut-ref="pt3" returning="ret"/> </aop:aspect>
-
通知類
public void afterReturning(Object ret) { System.out.println(ret); }
-
適用於返回後通知(after-returning)
第二種:
-
在通知類的方法中呼叫原始方法獲取返回值
-
原始方法
public int save() { System.out.println("user service running..."); return 100; }
-
AOP配置l
<aop:aspect ref="myAdvice"> <aop:pointcut id="pt2" expression="execution(* *(..)) "/> <aop:around method="around" pointcut-ref="pt2" /> </aop:aspect>
-
通知類
public Object around(ProceedingJoinPoint pjp) throws Throwable { Object ret = pjp.proceed(); return ret; }
-
適用於環繞通知(around)
3.9.3)通知獲取異常資料
第一種:通知類的方法中呼叫原始方法捕獲異常
-
在通知類的方法中呼叫原始方法捕獲異常
-
原始方法
public void save() { System.out.println("user service running..."); int i = 1/0; }
-
AOP配置
<aop:aspect ref="myAdvice"> <aop:pointcut id="pt4" expression="execution(* *(..)) "/> <aop:around method="around" pointcut-ref="pt4" /> </aop:aspect>
-
通知類
public Object around(ProceedingJoinPoint pjp) throws Throwable { Object ret = pjp.proceed(); //對此處呼叫進行try……catch……捕獲異常,或丟擲異常 return ret; }
-
適用於環繞通知(around)
第二種:
-
設定異常物件變數名
-
原始方法
public void save() { System.out.println("user service running..."); int i = 1/0; }
-
AOP配置
<aop:aspect ref="myAdvice"> <aop:pointcut id="pt4" expression="execution(* *(..)) "/> <aop:after-throwing method="afterThrowing" pointcut-ref="pt4" throwing="t"/> </aop:aspect>
-
通知類
public void afterThrowing(Throwable t){ System.out.println(t.getMessage()); }
-
適用於返回後通知(after-throwing)
4)AOP配置(註解)
4.1)註解開發AOP製作步驟
在XML格式基礎上
-
匯入座標(伴隨spring-context座標匯入已經依賴匯入完成)
-
開啟AOP註解支援
-
配置切面@Aspect
-
定義專用的切入點方法,並配置切入點@Pointcut
-
為通知方法配置通知型別及對應切入點@Before
4.2)註解開發AOP注意事項
1.切入點最終體現為一個方法,無參無返回值,無實際方法體內容,但不能是抽象方法
2.引用切入點時必須使用方法呼叫名稱,方法後面的()不能省略
3.切面類中定義的切入點只能在當前類中使用,如果想引用其他類中定義的切入點使用“類名.方法名()”引用
4.可以在通知型別註解後新增引數,實現XML配置中的屬性,例如after-returning後的returning屬性
4.3)AOP註解詳解
4.4.1)@Aspect
-
名稱:@Aspect
-
型別:註解
-
位置:類定義上方
-
作用:設定當前類為切面類
-
格式:
@Aspect public class AopAdvice { }
-
說明:一個beans標籤中可以配置多個aop:config標籤
4.4.2)@Pointcut
-
名稱:@Pointcut
-
型別:註解
-
位置:方法定義上方
-
作用:使用當前方法名作為切入點引用名稱
-
格式:
@Pointcut("execution(* *(..))") public void pt() { }
-
說明:被修飾的方法忽略其業務功能,格式設定為無參無返回值的方法,方法體內空實現(非抽象)
4.4.3)@Before
-
名稱:@Before
-
型別:註解
-
位置:方法定義上方
-
作用:標註當前方法作為前置通知
-
格式:
@Before("pt()") public void before(){ }
-
特殊引數:
- 無
4.4.4)@After
-
名稱:@After
-
型別:註解
-
位置:方法定義上方
-
作用:標註當前方法作為後置通知
-
格式:
@After("pt()") public void after(){ }
-
特殊引數:
- 無
4.4.5)@AfterReturning
-
名稱:@AfterReturning
-
型別:註解
-
位置:方法定義上方
-
作用:標註當前方法作為返回後通知
-
格式:
@AfterReturning(value="pt()",returning = "ret") public void afterReturning(Object ret) { }
-
特殊引數:
- returning :設定使用通知方法引數接收返回值的變數名
4.4.6)@AfterThrowing
-
名稱:@AfterThrowing
-
型別:註解
-
位置:方法定義上方
-
作用:標註當前方法作為異常後通知
-
格式:
@AfterThrowing(value="pt()",throwing = "t") public void afterThrowing(Throwable t){ }
-
特殊引數:
- throwing :設定使用通知方法引數接收原始方法中丟擲的異常物件名
4.4.7)@Around
-
名稱:@Around
-
型別:註解
-
位置:方法定義上方
-
作用:標註當前方法作為環繞通知
-
格式:
@Around("pt()") public Object around(ProceedingJoinPoint pjp) throws Throwable { Object ret = pjp.proceed(); return ret; }
-
特殊引數:
- 無
4.5)AOP註解開發通知執行順序控制(瞭解)
1.AOP使用XML配置情況下,通知的執行順序由配置順序決定,在註解情況下由於不存在配置順序的概念的概念,參照通知所配置的方法名字串對應的編碼值順序,可以簡單理解為字母排序
-
同一個通知類中,相同通知型別以方法名排序為準
-
不同通知類中,以類名排序為準
-
使用@Order註解通過變更bean的載入順序改變通知的載入順序
2.企業開發經驗
-
通知方法名由3部分組成,分別是字首、順序編碼、功能描述
-
字首為固定字串,例如baidu等,無實際意義
-
順序編碼為6位以內的整數,通常3位即可,不足位補0
-
功能描述為該方法對應的實際通知功能,例如exception、strLenCheck
-
制通知執行順序使用順序編碼控制,使用時做一定空間預留
-
003使用,006使用,預留001、002、004、005、007、008
-
使用時從中段開始使用,方便後期做前置追加或後置追加
-
最終順序以執行順序為準,以測試結果為準,不以設定規則為準
-
4.6)AOP註解驅動
-
名稱:@EnableAspectJAutoProxy
-
型別:註解
-
位置:Spring註解配置類定義上方
-
作用:設定當前類開啟AOP註解驅動的支援,載入AOP註解
-
格式:
@Configuration @ComponentScan("com.baidu") @EnableAspectJAutoProxy public class SpringConfig { }