1. 程式人生 > >(轉)spring aop(下)

(轉)spring aop(下)

pointcut too point stat 小時 size bin arch org

昨天記錄了Spring AOP學習的一部分(http://www.cnblogs.com/yanbincn/archive/2012/08/13/2635413.html),本來是想一口氣梳理完的。但是大晚上時間不夠(無奈一場奧運籃球總決賽耗費掉了2小時,不過的確相當精彩),又考慮到篇幅太長,閱讀性比較差,所以將後半部分更偏於應用的重起一篇隨筆。

  利用方式一的配置起來,可見代碼還是非常的厚重的,定義一個切面就要定義一個切面類,然而切面類中,就一個通知方法,著實沒有必要。所以Spring提供了,依賴aspectj的schema配置和基於aspectj 註解方式。這兩種方式非常簡介方便使用,也是項目中普遍的使用方式。梳理之:

4、方式二:schema配置

a、業務類:

技術分享 技術分享
/**
 * 業務類
 * 
 * @author yanbin
 * 
 */
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 + ":瞄改瞄啊!";
    }

}
技術分享

b、切面類:切面類中,包含了所有的通知

技術分享 技術分享
/**
 * 定義一個切面
 * 
 * @author yanbin
 * 
 */
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("刪除出錯啦");
    }

}
技術分享

c、配置文件:

技術分享 技術分享
<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="     
          http://www.springframework.org/schema/beans     
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd     
          http://www.springframework.org/schema/context     
          http://www.springframework.org/schema/context/spring-context-3.0.xsd 
          http://www.springframework.org/schema/aop     
          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    default-autowire="byName">

    <!-- ==============================利用spring 利用aspectj來配置AOP================================ -->

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

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

    <aop:config>
        <aop:aspect id="businessAspect" ref="aspectAdvice">
            <!-- 配置指定切入的對象 -->
            <aop:pointcut id="point_cut" expression="execution(* aop.schema.*.*(..))" />
            <!-- 只匹配add方法作為切入點
            <aop:pointcut id="except_add" expression="execution(* aop.schema.*.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>
技術分享

d、測試類:

技術分享 技術分享
public class Debug {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aop/schema_aop.xml");
        AspectBusiness business = (AspectBusiness) context.getBean("aspectBusiness");
        business.delete("貓");
    }

}
技術分享

5、方式三:aspectj註解

註解在項目中已經到處都是了,撇開一些優劣不提,開發的便利性和可讀性是非常的方便的。用來配置Spring AOP也非常簡單便利

a、業務類:

技術分享 技術分享
/**
 * 業務類
 * 
 * @author yanbin
 * 
 */
@Component
public class Business {

    /**
     * 切入點
     */
    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 + ":瞄改瞄啊!";
    }

}
技術分享

b、切面類:

技術分享 技術分享
/**
 * 定義切面
 * 
 * @Aspect : 標記為切面類
 * @Pointcut : 指定匹配切點
 * @Before : 指定前置通知,value中指定切入點匹配
 * @AfterReturning :後置通知,具有可以指定返回值
 * @AfterThrowing :異常通知
 * 
 * @author yanbin
 * 
 */
@Component
@Aspect
public class AspectAdvice {

    /**
     * 指定切入點匹配表達式,註意它是以方法的形式進行聲明的。
     */
    @Pointcut("execution(* aop.annotation.*.*(..))")
    public void anyMethod() {
    }

    /**
     * 前置通知
     * 
     * @param jp
     */
    @Before(value = "execution(* aop.annotation.*.*(..))")
    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
     *            返回值
     */
    @AfterReturning(value = "anyMethod()", returning = "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
     *            連接點
     */
    @Around(value = "execution(* aop.annotation.*.*(..))")
    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
     */
    @AfterThrowing(value = "execution(* aop.annotation.*.*(..))", throwing = "e")
    public void doThrow(JoinPoint jp, Throwable e) {
        System.out.println("刪除出錯啦");
    }

}
技術分享

c、配置:

技術分享 技術分享
<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="     
          http://www.springframework.org/schema/beans     
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd     
          http://www.springframework.org/schema/context     
          http://www.springframework.org/schema/context/spring-context-3.0.xsd 
          http://www.springframework.org/schema/aop     
          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
    default-autowire="byName">

    <context:component-scan base-package="aop.annotation" />
    <!-- 打開aop 註解 -->
    <aop:aspectj-autoproxy />

</beans>
技術分享

d、測試類:

技術分享 技術分享
/**
 * 測試類
 * 
 * @author yanbin
 * 
 */
public class Debug {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation_aop.xml");
        Business business = (Business) context.getBean("business");
        business.delete("貓");
    }

}

(轉)spring aop(下)