手把手教你學會用Spring AOP

        用了Spring很長時間了,一直想寫些AOP的東西,但一直沒有空閒,直到如今項目稍微進入正軌了,才趕忙寫寫。廢話很少說,先從AOP入門開始,後面再介紹AOP的原理(JDK動態代碼和CGLIB動態代碼的知識)。注:該部分適合於未接觸過Spring AOP的童鞋,若是是AOP老手,請直接繞過,不用打招呼^^php

       請尊重做者勞動成果,轉載請標明原文連接:html

       http://www.javashuo.com/article/p-qwsupnnn-ez.htmljava

1、環境準備web

       1.在Spring官網(地址見本文最後)下載springframework相關jar包,下載完後的jar包裏面會包含aop/aspects/context/beans/core等相關的jar。spring

       2.在AspectJ官網(AOP依賴包,地址見本文最後)下載AspectJ.jar,目前最新穩定版是1.9.1。express

       3.在Eclipse中,新建java project,而後在根目錄下新建lib目錄,並將第1步中下載的jar包所有copy到lib目錄下。app

       4.將第2步下載的AspectJ.jar解壓,並將解壓後的aspectjrt.jar、aspectjweaver.jar兩個jar包copy到lib目錄下。eclipse

       5.項目右鍵-build path-libraries-add jars,而後選擇lib中的所有jar包,點擊肯定。webapp

       6.在項目根目錄下新建配置文件applicationContext.xml,文件內容暫時爲空,到此環境準備完畢。ide

2、代碼示例

       瞭解AOP的童鞋都知道,使用AOP的方式有多少,這裏建議使用配置文件的方式,可以減小對代碼的注入,比較簡潔。

       1.新建切面類

package test; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class AspectAdvice { /** * 前置通知 * * @param jp */
    public void doBefore(JoinPoint jp) { System.out.println("===========進入before advice============ \n"); System.out.print("準備在" + jp.getTarget().getClass() + "對象上用"); System.out.print(jp.getSignature().getName() + "方法進行對 '"); System.out.print(jp.getArgs()[0] + "'進行刪除!\n\n"); System.out.println("要進入切入點方法了 \n"); } /** * 後置通知 * * @param jp * 鏈接點 * @param result * 返回值 */
    public void doAfter(JoinPoint jp, String result) { System.out.println("==========進入after advice=========== \n"); System.out.println("切入點方法執行完了 \n"); System.out.print(jp.getArgs()[0] + "在"); System.out.print(jp.getTarget().getClass() + "對象上被"); System.out.print(jp.getSignature().getName() + "方法刪除了"); System.out.print("只留下:" + result + "\n\n"); } /** * 環繞通知 * * @param pjp * 鏈接點 */
    public void doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("===========進入around環繞方法!=========== \n"); // 調用目標方法以前執行的動做
        System.out.println("調用方法以前: 執行!\n"); // 調用方法的參數
        Object[] args = pjp.getArgs(); // 調用的方法名
        String method = pjp.getSignature().getName(); // 獲取目標對象
        Object target = pjp.getTarget(); // 執行完方法的返回值:調用proceed()方法,就會觸發切入點方法執行
        Object result = pjp.proceed(); System.out.println("輸出:" + args[0] + ";" + method + ";" + target + ";" + result + "\n"); System.out.println("調用方法結束:以後執行!\n"); } /** * 異常通知 * * @param jp * @param e */
    public void doThrow(JoinPoint jp, Throwable e) { System.out.println("刪除出錯啦"); } }
View Code

       2.新建業務類

package test; public class AspectBusiness { public String delete(String obj) { System.out.println("==========調用切入點:" + obj + "說:你敢刪除我!===========\n"); return obj + ":瞄~"; } public String add(String obj) { System.out.println("================這個方法不能被切。。。============== \n"); return obj + ":瞄~ 嘿嘿!"; } public String modify(String obj) { System.out.println("=================這個也設置加入切吧====================\n"); return obj + ":瞄改瞄啊!"; } }
View Code

       3.在applicationContext.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/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 -->



    <!-- 聲明一個業務類 -->
    <bean id="aspectBusiness" class="test.AspectBusiness" />

    <!-- 聲明通知類 -->
    <bean id="aspectAdvice" class="test.AspectAdvice" />

    <aop:config>
        <aop:aspect id="businessAspect" ref="aspectAdvice">
            <!-- 配置指定切入的對象 -->
            <aop:pointcut id="point_cut" expression="execution(* test.*.*(..))" />
            <!-- 只匹配add方法做爲切入點 <aop:pointcut id="except_add" expression="execution(* test.*.add(..))" />
             -->

            <!-- 前置通知 -->
            <aop:before method="doBefore" pointcut-ref="point_cut" />
            <!-- 後置通知 returning指定返回參數 -->
            <aop:after-returning method="doAfter" pointcut-ref="point_cut" returning="result" />
            <aop:around method="doAround" pointcut-ref="point_cut"/>
            <aop:after-throwing method="doThrow" pointcut-ref="point_cut" throwing="e"/>
        </aop:aspect>
    </aop:config>
</beans>
View Code

       4.新建測試類

package test; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class StringTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); AspectBusiness business = (AspectBusiness) context.getBean("aspectBusiness"); business.delete("貓"); } }
View Code

3、運行結果

       運行結果以下所示:

===========進入before advice============ 準備在class test.AspectBusiness對象上用delete方法進行對 '貓'進行刪除! 要進入切入點方法了 ===========進入around環繞方法!=========== 調用方法以前: 執行! ==========調用切入點:貓說:你敢刪除我!=========== 輸出:貓;delete;test.AspectBusiness@3b69e7d1;貓:瞄~ 調用方法結束:以後執行! ==========進入after advice=========== 切入點方法執行完了 貓在class test.AspectBusiness對象上被delete方法刪除了只留下:null

       這樣AOP的示例就算完成了,本篇先不介紹切面、通知、切入點等的相關概念了,這些概念在百度上可謂信手拈來,若是有不瞭解,能夠自行百度。本篇先寫到這裏,後續再介紹AOP的相關原理。

 

       參考資料:

       1. Spring官網:https://spring.io/

       2. Spring5.0官網下載地址:https://repo.spring.io/webapp/#/artifacts/browse/tree/General/libs-release-local/org/springframework/spring/5.0.0.RELEASE

       3. AspectJ最新穩定版官網下載地址:http://www.eclipse.org/aspectj/downloads.php#stable_release

相關文章
相關標籤/搜索