昨天記錄了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("貓"); } }