SpringAOP使用擴展
在《初識Spring》中我們了解到Spring支持AOP且可配置方法的前置曾強和后置曾強,但其實Spring支持多種曾強類型。下面同過一些例子來介紹Spring的幾種常用的曾強。
異常拋出曾強
異常拋出曾強的特點是在目標方法拋出異常時織入曾強處理。首先我們要編寫一個實現異常曾強代碼的類,給類實現ThrowsAdvice接口。如下所示:
package cn.wz.aop; import java.lang.reflect.Method; import org.apache.log4j.Logger; import org.springframework.aop.ThrowsAdvice; public class ErrorLogger implements ThrowsAdvice { Logger log=Logger.getLogger(ErrorLogger.class); /** * 實現異常曾強代碼的方法 * @param method 目標方法名 * @param args 向目標方法傳入的參數 * @param target 目標方法所在的類的實例 * @param e 目標方法內所拋出的異常對象 */ public void afterThrowing(Method method,Object[] args,Object target,Exception e) { log.error(method.getName()+"發生異常:"+e); } }
上述代碼通過實現ThrowsAdvice接口實現異常拋出曾強,其中ThrowsAdvice接口中沒有定義任何方法,但我們在定義異常拋出的曾強方法時必須遵守以下方法簽名:
void afterThrowing([Method method,Object [] arguments,Object target,]Throwable ex)
這里Spring規定了方法名必須是“afterThrowing”。方法參數只有最后一個是必須的,前面三個參數是可選的,但是前面三個參數只能是要么都提供,要么都不提供!否則則無法實現曾強。下面編寫測試類進行測試:
package cn.wz.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ExceptionTest { public static void main(String[] args) throws Exception { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); ExceptionTest bean = context.getBean("test",ExceptionTest.class); bean.add(); } public void add() throws Exception { throw new Exception("錯誤"); } }
最終運行結果:
對于Spring配置文件的配置方法與前置增強和后置曾強的配置方法相同這里不再進行演示,
環繞曾強
環繞曾強在目標方法的前后都可以織入曾強處理。環繞增強是功能最強大的增強處理,Spring把目標方法的控制權全部交給了它。在環繞曾強處理中,可以獲取或修改目標方法的參數,返回值,可以對它進行異常處理,甚至可以決定目標方法是否執行!
好了下面來看看如何實現環繞曾強吧。首先還是要定義實現環繞曾強代碼的類,該類實現了MethodInterceptor接口的invoke()方法,在invoke()方法中編寫曾強代碼。
package cn.wz.aop; import java.lang.reflect.Method; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.log4j.Logger; public class ErrorLogger implements MethodInterceptor { Logger log=Logger.getLogger(ErrorLogger.class); public Object invoke(MethodInvocation arg0) throws Throwable { Method method = arg0.getMethod(); Object[] arguments = arg0.getArguments(); Object target = arg0.getThis(); log.info("調用"+target+"的"+method.getName()+"方法。方法入參:"+Arrays.toString(arguments)); try { Object result = arg0.proceed(); log.info("調用"+target+"的"+method.getName()+"方法。方法返回值:"+result); return result; } catch (Exception e) { log.error(method.getName()+"方法異常:"+e); } return null; } }
上述代碼通過MethodInterceptor接口實現了環繞增強。該接口要求實現invoke方法,其參數MethodInvocation不但瘋轉了目標方法及其入參數組,還封裝了被代理的目標對象。通過proceed方法可以調用目標對象響應的方法,從而實現對目標方法的完全控制。借助異常拋出曾強的測試代碼進行測試其運行結果如下:
使用注解實現曾強
除了實現Spring提供的特定接口外,Spring還可以通過集成AspectJ實現了以注解的方式定義增強類。大大減少了配置文件中的工作量。
注意:使用Aspectj是要確保JDK的版本是5.0或以上的版本,否則將無法使用注解技術,其次還要引入asm模塊的jar包到項目中
前置曾強和后置曾強類:
package cn.wz.aop; import org.apache.log4j.Logger; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class UserLogger { private static final Logger log=Logger.getLogger(UserLogger.class); @Before("execution(public void add())") public void before(){ log.info("前置增強"); } @AfterReturning("execution(public void add())") public void afterReturning(){ log.info("后置增強"); } }
在Spring配置文件中的配置如下:
異常拋出增強類:
package cn.wz.aop; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; @Aspect public class Error_Logger { private static final Logger log=Logger.getLogger(UserLogger.class); @AfterThrowing(pointcut="execution(public void add())" ,throwing="e") public void agterThrowing(JoinPoint jp,Exception e){ log.error(jp.getSignature().getName()+"發生異常:"+e); } }
環繞增強類:
package cn.wz.aop; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class ArounsLogger { private static final Logger log=Logger.getLogger(UserLogger.class); @Around("execution(public void add())") public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{ System.out.println("前置增強"); Object obj = jp.proceed();//調用原始方法 System.out.println("后置增強"); return obj; } }
來自:http://www.cnblogs.com/wangzheand/p/5939618.html