Spring??AOP的兩種使用方法
前言
記錄下 Spring AOP 的兩種使用方式,不談概念,只記錄兩種方式的使用例子
- 注解方式
- xml 配置方式
1 注解方式
1.1 聲明目標類 UserDao 類
@Repository("userDao")
public class UserDao {
public void addUser() {
System.out.println("?? 攔截的方法 addUser 開始執(zhí)行");
}
}1.2 聲明切面 AnnotationAspect 類
@Aspect
@Component
public class AnnotationAspect {
// 定義切入點表達式, 使用一個返回值為 void、方法體為空的方法來命名切入點
@Pointcut("execution(* com.fairy.springmvc.aspectj.annotation.*.*(..))")
private void customPointCut(){}
// 前置通知
@Before("customPointCut()")
public void myBefore(JoinPoint joinPoint){
System.out.print("前置通知:模擬執(zhí)行權(quán)限檢查..,");
System.out.print("目標類是:" + joinPoint.getTarget());
System.out.println(",被植入增強處理的目標方法為:" + joinPoint.getSignature().getName());
}
// 后置通知
@AfterReturning(value="customPointCut()")
public void myAfterReturning(JoinPoint joinPoint) {
System.out.print("后置通知:模擬記錄日志..,");
System.out.println("被植入增強處理的目標方法為:" + joinPoint.getSignature().getName());
}
/**
* 環(huán)繞通知
* ProceedingJoinPoint 是 JoinPoint的子接口,表示可執(zhí)行目標方法
* 1.必須是 Object 類型的返回值
* 2.必須接收一個參數(shù),類型為 ProceedingJoinPoint
* 3.必須 throws Throwable
*/
@Around("customPointCut()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
// 開始
System.out.println("環(huán)繞開始:執(zhí)行目標方法之前,模擬開啟事務(wù)..,");
// 執(zhí)行當前目標方法
Object obj = proceedingJoinPoint.proceed();
// 結(jié)束
System.out.println("環(huán)繞結(jié)束:執(zhí)行目標方法之后,模擬關(guān)閉事務(wù)..,");
return obj;
}
/**
* 異常通知處理
* @param joinPoint
* @param e
*/
@AfterThrowing(value="customPointCut()",throwing="e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e){
System.out.println("異常通知:出錯了" + e.getMessage());
}
// 最終通知
@After("customPointCut()")
public void myAfter(){
System.out.println("最終通知:模擬方法結(jié)束后釋放資源..");
}
}1.3 聲明配置
開啟@AspectJ的注解配置方式,有兩種方式
1 在 xml 文件,添加以下配置:
<!-- 啟動基于注解的聲明式 AspectJ 支持 --> <aop:aspectj-autoproxy />
2 使用了 Java 代碼風(fēng)格的配置,則需使用 EnableAspectJAutoProxy 注解
示例如下
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.fairy.springmvc")
public class ApplicationConfig {
....
}1.4 測試用例
public class TestCase {
@Test
public void testAnnotation() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"spring-test.xml");
// 從容器中獲得內(nèi)容
UserDao userDao= (UserDao) applicationContext.getBean("userDao");
// 執(zhí)行方法
userDao.addUser();
}
}運行結(jié)果如下:
環(huán)繞開始:執(zhí)行目標方法之前,模擬開啟事務(wù)..,
前置通知:模擬執(zhí)行權(quán)限檢查..,
目標類是:com.fairy.springmvc.aspectj.annotation.UserDao@4a699efa,
被植入增強處理的目標方法為:addUser
?? 攔截的方法 addUser 開始執(zhí)行
后置通知:模擬記錄日志..,被植入增強處理的目標方法為:addUser
最終通知:模擬方法結(jié)束后釋放資源..
環(huán)繞結(jié)束:執(zhí)行目標方法之后,模擬關(guān)閉事務(wù)..,
通過輸出結(jié)果看出,符合預(yù)期。
2 XML 配置方式
2.1 聲明目標類 CompanyDao
@Repository("companyDao")
public class CompanyDao {
public void addCompany() {
System.out.println("?? 真正的業(yè)務(wù)處理:add company ??");
}
public void exception() throws Exception {
throw new Exception("業(yè)務(wù)異常了");
}
}2.2 聲明切面攔截類 XmlAspect
@Component("xmlAspectConfig")
public class XmlAspect {
public void printUnderscore() {
System.out.println("------------------------------------------------");
}
/**
* 在核心業(yè)務(wù)執(zhí)行前執(zhí)行,不能阻止核心業(yè)務(wù)的調(diào)用
* @param joinPoint
*/
public void beforeAdvice(JoinPoint joinPoint) {
printUnderscore();
System.out.println("1?? 通知:beforeAdvice 執(zhí)行開始");
System.out.println(" 執(zhí)行核心業(yè)務(wù)邏輯前,可以做一些前置的安全性的檢測等");
System.out.println(" 通知:beforeAdvice 執(zhí)行結(jié)束");
printUnderscore();
}
/**
* 核心業(yè)務(wù)退出后,不管是正常結(jié)束還是異常退出,均執(zhí)行此通知
* @param joinPoint
*/
public void afterAdvice(JoinPoint joinPoint) {
printUnderscore();
System.out.println("4?? 通知:afterAdvice 執(zhí)行開始");
System.out.println(" 此處可以對返回值做進一步的處理");
System.out.println(" 通知:afterAdvice 執(zhí)行結(jié)束");
}
/**
* 核心業(yè)務(wù)調(diào)用正常退出后,不管是否有返回值,只要是正常退出,都會執(zhí)行此通知
* @param joinPoint
*/
public void afterReturningAdvice(JoinPoint joinPoint) {
printUnderscore();
System.out.println("2?? 通知:afterReturningAdvice 執(zhí)行開始");
System.out.println(" 此處可以對返回值做進一步處理");
System.out.println(" 通知:afterReturningAdvice 執(zhí)行結(jié)束");
}
/**
* 核心業(yè)務(wù)邏輯調(diào)用異常退出后,執(zhí)行此通知,處理錯誤信息
* @param e
*/
public void afterThrowingAdvice(Exception e) {
printUnderscore();
System.out.println("3?? 通知:afterThrowingAdvice 執(zhí)行開始");
System.out.println(" 錯誤信息:" + e.getMessage());
System.out.println(" 此處意味著,在核心業(yè)務(wù)邏輯出錯時,捕獲異常,并可以做一些日志記錄相關(guān)的操作");
}
/**
* 手動控制調(diào)用核心業(yè)務(wù)邏輯,以及調(diào)用前和調(diào)用后的處理
* @param pjp
*/
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
// 開始
System.out.println("5?? 環(huán)繞開始:執(zhí)行目標方法之前");
System.out.println(" 此處可以做類似于 Before Advice 的事情");
// 調(diào)用核心邏輯,執(zhí)行當前目標方法
Object obj = pjp.proceed();
// 打印下劃線
printUnderscore();
// 結(jié)束
System.out.println(" 此處可以做類似于 After Advice 的事情");
System.out.println("5?? 環(huán)繞結(jié)束:執(zhí)行目標方法之后");
return obj;
}
}2.3 聲明 XML 配置
<!-- 基于 XML 文件的配置進行聲明,注意和 aop:aspectj-autoproxy 的區(qū)別 -->
<aop:config proxy-target-class="true">
<!-- 基于 aspect 配置一個完整的切面 -->
<aop:aspect id="aspectXmlConfigExample" ref="xmlAspectConfig">
<!-- 切點配置,可以配置多個切點 -->
<aop:pointcut id="xmlPointCut"
expression="execution(* com.fairy.springmvc.aspectj.xml.CompanyDao.*(..))"/>
<aop:after-returning method="afterReturningAdvice" pointcut-ref="xmlPointCut" />
<aop:after-throwing method="afterThrowingAdvice" pointcut-ref="xmlPointCut" throwing="e"/>
<aop:after method="afterAdvice" pointcut-ref="xmlPointCut" />
<aop:around method="aroundAdvice" pointcut-ref="xmlPointCut" />
<aop:before method="beforeAdvice" pointcut-ref="xmlPointCut" />
</aop:aspect>
</aop:config>注意:
值得注意的是
around與before和after的執(zhí)行順序。3者的執(zhí)行順序取決于在xml中的配置順序。
2.3 測試用例
public class TestCase {
@Test
public void testAnnotation() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"spring-test.xml");
CompanyDao companyDao = (CompanyDao) applicationContext.getBean("companyDao");
companyDao.addCompany();
// companyDao.exception();
}
}輸出結(jié)果如下:
-------------------------------
5?? 環(huán)繞開始:執(zhí)行目標方法之前
此處可以做類似于 Before Advice 的事情
------------------------------------------------
1?? 通知:beforeAdvice 執(zhí)行開始
執(zhí)行核心業(yè)務(wù)邏輯前,可以做一些前置的安全性的檢測等
通知:beforeAdvice 執(zhí)行結(jié)束
------------------------------------------------
?? 真正的業(yè)務(wù)處理:add company ??
------------------------------------------------
2?? 通知:afterReturningAdvice 執(zhí)行開始
此處可以對返回值做進一步處理
通知:afterReturningAdvice 執(zhí)行結(jié)束
------------------------------------------------
4?? 通知:afterAdvice 執(zhí)行開始
此處可以對返回值做進一步的處理
通知:afterAdvice 執(zhí)行結(jié)束
------------------------------------------------
此處可以做類似于 After Advice 的事情
5?? 環(huán)繞結(jié)束:執(zhí)行目標方法之后
結(jié)果符合預(yù)期。
到此這篇關(guān)于Spring AOP 的兩種使用方法的文章就介紹到這了,更多相關(guān)Spring AOP 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解spring boot容器加載完后執(zhí)行特定操作
這篇文章主要介紹了詳解spring boot容器加載完后執(zhí)行特定操作,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Hibernate框架數(shù)據(jù)分頁技術(shù)實例分析
這篇文章主要介紹了Hibernate框架數(shù)據(jù)分頁技術(shù),結(jié)合實例形式分析了Hibernate框架實現(xiàn)數(shù)據(jù)分頁的原理,步驟與相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2016-03-03
使用注解@Validated效驗VO參數(shù)是否合規(guī)
這篇文章主要為大家介紹了使用注解@Validated效驗VO參數(shù)是否合規(guī)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
解決Eclipse配置Tomcat出現(xiàn)Cannot create a server using the selected
這篇文章主要介紹了解決Eclipse配置Tomcat出現(xiàn)Cannot create a server using the selected type錯誤的相關(guān)資料,需要的朋友可以參考下2017-02-02
Java使用GZIP壓縮導(dǎo)致HTTP請求返回亂碼問題解決
這篇文章主要為大家介紹了Java壓縮GZIP導(dǎo)致HTTP請求返回亂碼問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

