您好,登錄后才能下訂單哦!
這篇“Spring AOP如何使用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Spring AOP如何使用”文章吧。
@Repository("userDao") public class UserDao { public void addUser() { System.out.println("???? 攔截的方法 addUser 開始執行"); } }
@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("前置通知:模擬執行權限檢查..,"); 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()); } /** * 環繞通知 * ProceedingJoinPoint 是 JoinPoint的子接口,表示可執行目標方法 * 1.必須是 Object 類型的返回值 * 2.必須接收一個參數,類型為 ProceedingJoinPoint * 3.必須 throws Throwable */ @Around("customPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ // 開始 System.out.println("環繞開始:執行目標方法之前,模擬開啟事務..,"); // 執行當前目標方法 Object obj = proceedingJoinPoint.proceed(); // 結束 System.out.println("環繞結束:執行目標方法之后,模擬關閉事務..,"); 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("最終通知:模擬方法結束后釋放資源.."); } }
開啟@AspectJ
的注解配置方式,有兩種方式
1 在 xml
文件,添加以下配置:
<!-- 啟動基于注解的聲明式 AspectJ 支持 --> <aop:aspectj-autoproxy />
2 使用了 Java
代碼風格的配置,則需使用 EnableAspectJAutoProxy
注解
示例如下
@Configuration @EnableAspectJAutoProxy @ComponentScan("com.fairy.springmvc") public class ApplicationConfig { .... }
public class TestCase { @Test public void testAnnotation() throws Exception { ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "spring-test.xml"); // 從容器中獲得內容 UserDao userDao= (UserDao) applicationContext.getBean("userDao"); // 執行方法 userDao.addUser(); } }
運行結果如下:
環繞開始:執行目標方法之前,模擬開啟事務..,
前置通知:模擬執行權限檢查..,
目標類是:com.fairy.springmvc.aspectj.annotation.UserDao@4a699efa,
被植入增強處理的目標方法為:addUser
???? 攔截的方法 addUser 開始執行
后置通知:模擬記錄日志..,被植入增強處理的目標方法為:addUser
最終通知:模擬方法結束后釋放資源..
環繞結束:執行目標方法之后,模擬關閉事務..,
通過輸出結果看出,符合預期。
@Repository("companyDao") public class CompanyDao { public void addCompany() { System.out.println("???? 真正的業務處理:add company ????"); } public void exception() throws Exception { throw new Exception("業務異常了"); } }
@Component("xmlAspectConfig") public class XmlAspect { public void printUnderscore() { System.out.println("------------------------------------------------"); } /** * 在核心業務執行前執行,不能阻止核心業務的調用 * @param joinPoint */ public void beforeAdvice(JoinPoint joinPoint) { printUnderscore(); System.out.println("1?? 通知:beforeAdvice 執行開始"); System.out.println(" 執行核心業務邏輯前,可以做一些前置的安全性的檢測等"); System.out.println(" 通知:beforeAdvice 執行結束"); printUnderscore(); } /** * 核心業務退出后,不管是正常結束還是異常退出,均執行此通知 * @param joinPoint */ public void afterAdvice(JoinPoint joinPoint) { printUnderscore(); System.out.println("4?? 通知:afterAdvice 執行開始"); System.out.println(" 此處可以對返回值做進一步的處理"); System.out.println(" 通知:afterAdvice 執行結束"); } /** * 核心業務調用正常退出后,不管是否有返回值,只要是正常退出,都會執行此通知 * @param joinPoint */ public void afterReturningAdvice(JoinPoint joinPoint) { printUnderscore(); System.out.println("2?? 通知:afterReturningAdvice 執行開始"); System.out.println(" 此處可以對返回值做進一步處理"); System.out.println(" 通知:afterReturningAdvice 執行結束"); } /** * 核心業務邏輯調用異常退出后,執行此通知,處理錯誤信息 * @param e */ public void afterThrowingAdvice(Exception e) { printUnderscore(); System.out.println("3?? 通知:afterThrowingAdvice 執行開始"); System.out.println(" 錯誤信息:" + e.getMessage()); System.out.println(" 此處意味著,在核心業務邏輯出錯時,捕獲異常,并可以做一些日志記錄相關的操作"); } /** * 手動控制調用核心業務邏輯,以及調用前和調用后的處理 * @param pjp */ public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable { // 開始 System.out.println("5?? 環繞開始:執行目標方法之前"); System.out.println(" 此處可以做類似于 Before Advice 的事情"); // 調用核心邏輯,執行當前目標方法 Object obj = pjp.proceed(); // 打印下劃線 printUnderscore(); // 結束 System.out.println(" 此處可以做類似于 After Advice 的事情"); System.out.println("5?? 環繞結束:執行目標方法之后"); return obj; } }
<!-- 基于 XML 文件的配置進行聲明,注意和 aop:aspectj-autoproxy 的區別 --> <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
的執行順序。3
者的執行順序取決于在xml
中的配置順序。
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(); } }
輸出結果如下:
-------------------------------
5?? 環繞開始:執行目標方法之前
此處可以做類似于 Before Advice 的事情
------------------------------------------------
1?? 通知:beforeAdvice 執行開始
執行核心業務邏輯前,可以做一些前置的安全性的檢測等
通知:beforeAdvice 執行結束
------------------------------------------------
???? 真正的業務處理:add company ????
------------------------------------------------
2?? 通知:afterReturningAdvice 執行開始
此處可以對返回值做進一步處理
通知:afterReturningAdvice 執行結束
------------------------------------------------
4?? 通知:afterAdvice 執行開始
此處可以對返回值做進一步的處理
通知:afterAdvice 執行結束
------------------------------------------------
此處可以做類似于 After Advice 的事情
5?? 環繞結束:執行目標方法之后
結果符合預期。
以上就是關于“Spring AOP如何使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。