Spring AOP定義切面java
Ⅰ 首先介紹一下寫Spring Aop思路
spring
1、首先在項目中加入aop所須要的jarexpress
aopalliance-1.0.jar
aspectjweaver-1.6.11.jar
commons-logging-1.1.1.jar
spring-aop-3.0.5.RELEASE.jar
spring-aspects-3.0.5.RELEASE.jar
spring-beans-3.0.5.RELEASE.jar
spring-context-3.0.5.RELEASE.jar
spring-context-support-3.0.5.RELEASE.jar
spring-core-3.0.5.RELEASE.jar
spring-expression-3.0.5.RELEASE.jarapp
2、在spring 項目核心配置文件中加入aop的命名空間函數
<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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
3、聲明一個切面類spa
一、首先要將這個類放入容器中,基於註解,在類頭信息加入@Component代理
二、將這個類聲明成切面類,在頭信息加入@Aspect註解code
三、能夠基於切面中的方法,好比前置通知,後置通知,返回通知,異常通知,以及環繞通知寫本身的業務邏輯,定義切點"execution(* com.liyi.service.*.*(..))",即那些方法須要執行這些方法。若是想獲取到方法的名字和參數,能夠在方法中加入JoinPoint參數,能夠獲取到進入切面的方法細節。orm
3.1 前置通知:執行目標方法前攔截到的方法。沒有特殊注意的地方,只須要一個鏈接點,JoinPoint,便可獲取攔截目標方 法以及請求參數。xml
3.2 後置通知: 切面的後置通知,無論方法是否拋出異常,都會走這個方法。只須要一個鏈接點,JoinPoint,便可獲取當 前結束的方法名稱。
3.3 返回通知: 在方法正常執行經過以後執行的通知叫作返回通知。此時注意,不單單使用JoinPoint獲取鏈接 點信息,同時要在返回通知註解裏寫入,resut="result"。在切面方法參數中加入Object result,用於接受返回通知 的返回結果。若是目標方法方法是void返回類型則返回NULL
3.4 異常通知: 在執行目標方法過程當中,若是方法拋出異常則會走此方法。和返回通知很類似,在註解中 加入,throwing="ex",在切面方法中加入Exection ex用於接受異常信息
3.5 環繞通知:環繞通知須要攜帶ProceedingJoinPoint 這個類型的參數,環繞通知相似於動態代理的全過程 ProceedingJoinPoint類型的參數能夠決定是否執行目標函數環繞通知必須有返回值。其實就是包含了全部通知的全 過程
4、最後別忘了在applicationContent.xml中聲明aspect的代理對象,即初始化spring 容器的時候,spring自動對切點生成代理對象
<!-- 配置aspect 自動爲匹配的類 產生代理對象 -->
<aop:aspectj-autoproxy>
Ⅱ 接下來 直接粘貼代碼,很直觀。
一、aspect切面類
package com.liyi.aop; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class LoggingAspect { /** * 切面的前置方法 即方法執行前攔截到的方法 記錄並輸出 * 在目標方法執行以前的通知 * @param joinPoint */ @Before("execution(* com.liyi.service.*.*(..))")//第一個星號是否方法的返回值 第二個星是隻service的全部子包 另外一個是任意方法 public void beforeMethod(JoinPoint joinPoint){ System.out.println("======================方法開始======================"); Object object = joinPoint.getSignature(); String methodName = joinPoint.getSignature().getName(); List<Object> list = Arrays.asList(joinPoint.getArgs()); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String rightnow=sdf.format(date); System.out.println(rightnow+"執行了【"+object+"方法開始執行......】"); System.out.println("******參數"+list+"******"); } /** * 切面的後置方法,無論拋不拋異常都會走此方法 * 在目標方法執行以後的通知 * @param joinPoint */ @After("execution(* com.liyi.service.*.*(..))") public void afterMethod(JoinPoint joinPoint){ Object object = joinPoint.getSignature(); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String rightnow=sdf.format(date); System.out.println(rightnow+"執行了【"+object+"方法結束......】"); } /** * 在方法正常執行經過以後執行的通知叫作返回通知 * 能夠返回到方法的返回值 在註解後加入returning * @param joinPoint */ @AfterReturning(value="execution(* com.liyi.service.*.*(..))",returning="result") public void afterReturn(JoinPoint joinPoint,Object result ){ Object object = joinPoint.getSignature(); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String rightnow=sdf.format(date); System.out.println(rightnow+"執行了【"+object+"方法正常執行結束......】"+"【返回結果:"+result+"】"); System.out.println("√√√√√√√√√√√√√√√√√√√√√√方法結束√√√√√√√√√√√√√√√√√√√√√√"); } /** * 在目標方法非正常執行完成 發生異常 拋出異常的時候會走此方法 * 得到異常能夠用throwing * @param joinPoint * @param ex */ @AfterThrowing(value="execution(* com.liyi.service.*.*(..))",throwing="ex") public void afterThrowing(JoinPoint joinPoint,Exception ex ){ Object object = joinPoint.getSignature(); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String rightnow=sdf.format(date); System.out.println(rightnow+"執行了【"+object+"方法發生異常......】"+"【異常報告:"+ex+"】"); System.out.println("xxxxxxxxxxxxxxxxxx方法發生異常結束xxxxxxxxxxxxxxxxxx"); } /** * 環繞通知須要攜帶ProceedingJoinPoint 這個類型的參數 * 環繞通知相似於動態代理的全過程 ProceedingJoinPoint類型的參數能夠決定是否執行目標函數 * 環繞通知必須有返回值 * @param proceedingJoinPoint * @return */ // @Around(value="execution(* com.liyi.service.*.*(..))") // public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){ // Object result=null; // Object classMethod=proceedingJoinPoint.getSignature(); // Date date = new Date(); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // String rightnow=sdf.format(date); // try { // //前置通知 // System.out.println(rightnow+"環繞通知執行了【"+classMethod+"方法開始執行......】"); // //執行目標方法 // result = proceedingJoinPoint.proceed(); // //返回通知 // System.out.println(rightnow+"環繞通知正常執行【"+classMethod+"方法完畢......】"+"【返回結果:】"+result); // } catch (Throwable e) { // // TODO Auto-generated catch block // e.printStackTrace(); // //異常通知 // System.out.println(rightnow+"環繞通知非正常執行【"+classMethod+"方法完畢,拋出異常......】"+"【返回異常:】"+e); // } // //後置通知 // System.out.println(rightnow+"環繞通知執行【"+classMethod+"方法完畢】"); // return result; // } }