Spring aop 前置通知、後置通知、返回通知、 異常通知 、後置通知

                                                            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;
//    }
}
相關文章
相關標籤/搜索