spring(AOP通知)
切面
切面是封裝通用業務邏輯的組件,可以作用到其他組件上。是spring組件中的某個方法、無返回類型、參數類型與通知類型有關。
一個切面 開啓數據庫 關閉數據庫 開啓事務 檢查登錄賬號狀態 監測賬號權限
切點
用於指定哪些組件哪方法使用切面組件,Spring提供表達式來實現該制定。
通知
用於指定組件作用到目標組件的具體位置。
連接點(Joinpoint)
增強程序執行的某個特定位置(要在哪個地方做增強操作)。Spring僅支持方法的連接點,既僅能在方法調用前,方法調用後,方法拋出異常時等這些程序執行點進行織入增強。
切點(Pointcut)
切點是一組連接點的集合。AOP通過“切點”定位特定的連接點。通過數據庫查詢的概念來理解切點和連接點的關係再適合不過了:連接點相當於數據庫中的記錄,而切點相當於查詢條件。
增強(Advice)
增強是織入到目標類連接點上的一段程序代碼。表示要在連接點上做的操作。
切面(Aspect)
切面由切點和增強(引介)組成(可以包含多個切點和多個增強),它既包括了橫切邏輯的定義,也包括了連接點的定義,SpringAOP就是負責實施切面的框架,它將切面所定義的橫切邏輯織入到切面所指定的鏈接點中。
註解使用
@aspect 定義切面
@pointcut 定義切點
@before 標註Before Advice定義所在的方法
@afterreturning 標註After Returning Advice定義所在的方法
@afterthrowing 標註After Throwing Advice定義所在的方法
@after 標註 After(Finally) Advice定義所在的方法
@around 標註Around Advice定義所在的方法
包結構如下圖
1.AOP通知(配置xml文件)
QieMian1.java
public class QieMian1 {
public void qianzhi(JoinPoint jp) {
System.out.println("前置通知");
Object [] os = jp.getArgs();
for (Object object : os) {
System.out.println("參數列表爲:"+object);
}
}
public void houzhi(Object a) {
System.out.println("後置通知"+a);
}
public void yichang(JoinPoint jp,Throwable ta) {
System.out.println("異常通知");
ta.printStackTrace();
}
public void zuizhong() {
System.out.println("最終通知");
}
public void huanrao(ProceedingJoinPoint pjp) {
try {
System.out.println("環繞前");
pjp.proceed();
System.out.println("環繞後");
} catch (Throwable e) {
// TODO Auto-generated catch block
System.out.println("環繞異常");
e.printStackTrace();
}finally {
System.out.println("環繞最終");
}
}
}
ApplicationContext.xml
<!-- 切面1 -->
<bean id="qieMian1" class="com.zy.spring.tools.aop.QieMian1"></bean> <!-- 創建一個切面的bean -->
<aop:config> <!-- aop配置標籤 -->
<aop:pointcut expression="execution(* com.zy.spring.service.*.*(..))" id="pc1"/> <!-- 創建一個切點 -->
<aop:aspect order="1" ref="qieMian1"><!-- 創建一個切面 order是切面創建的順序 ref鏈接上面創建的切面bean -->
<aop:before method="qianzhi" pointcut-ref="pc1"/><!-- 前置通知 -->
<aop:after-returning method="houzhi" pointcut-ref="pc1" returning="a"/> <!-- 後置通知 returning返回參數-->
<aop:after-throwing method="yichang" pointcut-ref="pc1" throwing="ta"/> <!-- 異常通知 throwing返回參數-->
<aop:after method="zuizhong" pointcut-ref="pc1"/> <!-- 最終通知 -->
<aop:around method="huanrao" pointcut-ref="pc1"/> <!-- 環繞通知 -->
</aop:aspect>
</aop:config>
1、execution:
Spring AOP僅支持方法執行類型的Joinpoint 所以execution將會是我們用的最多的標誌符,用它來幫我們匹配擁有指定方法前面的Joinpoint。
匹配方法execution
execution(返回類型 類的路徑.類名.函數名(參數類型1,參數類型2))
execution(String com.chinasofti.Target.save(String))
execution(* com.chinasofti.Target.save(String))
execution(* com.chinasofti.*.save(String))
execution(* com.chinasofti..(String))
execution(* com….(…))
2、Within:
Within標誌符只接受類型聲明,它將匹配指定類型下所有的Joinpoint。
匹配類within
匹配到類
<aop:pointcut id=“targetPintcut” expression=“within(com.chinasofti.Target)”/>
調用這個類中的任何一個方法,都會走通知
匹配到包下的類
<aop:pointcut id=“targetPintcut” expression=“within(com.chinasofti.*)”/>
調用這個包下的任何一個類中的方法,都會走通知
匹配到包下及子包下的類
<aop:pointcut id=“targetPintcut” expression=“within(com…*)”/>
調用com這個包下的,所有子包及其一個類中的方法,都會走通知
2.AOP通知(註解配置)
QieMian2.java
@Aspect//定義切面
@Component//註冊bean
public class QieMian2 {
@Pointcut("execution(* com.zy.spring.service.*.*(..))") //標記切點規則
public void pointcut() {};//創建一個空的方法,相當於切入方法
@Before("pointcut()") //前置通知 切點就是上面創建的pointcut()方法
public void qianzhi(JoinPoint jp) {
System.out.println("註解前置通知");
Object [] os = jp.getArgs();
for (Object object : os) {
System.out.println("參數列表爲:"+object);
}
}
@AfterReturning(pointcut="pointcut()",returning="a")//後置通知 returning是方法中定義的參數
public void houzhi(Object a) {
System.out.println("註解後置通知"+a);
}
@AfterThrowing(pointcut="pointcut()",throwing="ta")//異常通知 throwing是方法中定義的參數
public void yichang(JoinPoint jp,Throwable ta) {
System.out.println("註解異常通知");
ta.printStackTrace();
}
@After("pointcut()")//最終通知
public void zuizhong() {
System.out.println("註解最終通知");
}
@Around("pointcut()")//環繞通知
public void huanrao(ProceedingJoinPoint pjp) {
try {
System.out.println("註解環繞前");
pjp.proceed();//放行
System.out.println("註解環繞後");
} catch (Throwable e) {
// TODO Auto-generated catch block
System.out.println("註解環繞異常");
e.printStackTrace();
}finally {
System.out.println("註解環繞最終");
}
}
}
ApplicationContext.xml
<!-- 註解掃描AOP -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
使用註解aop功能,加入aop1的註解掃描即可。
博客園鏈接