1. 程式人生 > >Spring學習筆記四(AOP中的通知引數和註解開發)

Spring學習筆記四(AOP中的通知引數和註解開發)

 1.前言

上一篇部落格介紹瞭如何通過AOP來切入我們想實現的公共性的功能,這篇部落格來講一下,當我們攔截到方法後,如何來獲取通知引數。這也是AOP的精髓所在,通過AOP可以實現偷樑換柱的功能。我們把原來要執行的方法的引數獲取到,然後換一套引數執行。下面來跟著我看一下吧!

 2.AOP的通知引數

有時我們想通過AOP攔截到我們要加入通知的切點類的引數,通俗的說就像拿到攔截的方法的引數值,然後如果不合適的話,我們可以修改一下或者做一些其他的操作。例如使用者登入的功能,我們可以把驗證身份的功能抽離出來,然後在AOP中攔截到登陸方法中的引數,通過判斷使用者名稱來決定做下一步的操作。那麼如何來取出使用者名稱呢。

如果需要在通知方法中獲取原始方法的呼叫引數,需要在通知方法的第一個形參位置宣告JoinPoint型別的引數,使用該引數呼叫getArgs()方法可以獲得原始方法的呼叫引數列表Object[]

<span style="font-size:18px;">package com.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

//通知類
public class MyAdvice {
	
	
	public void before(JoinPoint jp,String a,int b){
		//Object[] objs = jp.getArgs();
		//System.out.println("before......"+objs[0]+","+objs[1]);
		System.out.println("before......"+a+","+b);
	}
	public void after(JoinPoint jp){
		System.out.println("after......");
	}
	public void afterReturning(JoinPoint jp,Object abc){
		System.out.println("afterReturning......"+abc);
	}
	public void afterThrowing(JoinPoint jp){
		System.out.println("afterThrowing......");
	}
	
	//具有公共性的功能
	public Object fn(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("aaaaaaa");
		//獲取到執行的引數
		Object[] obj=	pjp.getArgs();
		for (Object lb:obj) {
			System.out.println(lb);
		}
		
		//進行偷樑換柱的功能
	Object ob=	pjp.proceed(new Object[]{new Integer(6),new Integer(9)});
		System.out.println("bbbbbbbbbbbbbbb");
		return ob;
	}
}
</span>

注意:所有通知都可以通過JoinPoint獲得通知的引數,但是隻有around類別才可以執行替代攔截方法。

 3.AOP通知返回值

1.只有afterReturning 與 around可以獲取方法的返回值

        2.afterReturning:在配置中設定returning屬性,值是變數名的值,與方法的形參進行對應

              <aop:after-returning method="afterReturning"returning="abc"/>

              publicvoid afterReturning(JoinPoint jp,Object abc){

                     System.out.println("afterReturning......"+abc);

              }

       3.around:直接通過程式中的原始方法呼叫獲取,該方法返回值即為原始方法的返回值

              publicObject around(ProceedingJoinPoint pjp) throws Throwable{

                     System.out.println("aroundbefore......");

                     //呼叫原始方法

                     Objectobj = pjp.proceed();

                     System.out.println("around after......"+obj);

                     return obj;      說明:對原始方法攔截後,最終的執行返回值取決於這裡

              }

 4.AOP的註解開發

註解開發也特別的簡單,下面給出一個例項,與平常的XML配置類似

<span style="font-size:18px;">package cn.itcast.aop.annotation;

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.aspectj.lang.annotation.Pointcut;


//定義切面類
@Aspect
public class BookAdvice {
	//切面
	@Pointcut("execution(* cn.itcast.aop.annotation.BookService.add(..))")
	private void pt(){}
	
	//切點的順序
	@Before("BookAdvice.pt()")
	public void before(JoinPoint jp){
		System.out.println("before running......");
	}
	@After("BookAdvice.pt()")
	public void after(){
		System.out.println("after running......");
	}
	@AfterReturning(value="BookAdvice.pt()",returning="abc")
	public void afterReturning(Object abc){
		System.out.println("afterReturning running......"+abc);
	}
	@AfterThrowing(value="execution(* cn.itcast.aop.annotation.BookService.add(..))",throwing="t")
	public void afterThrowing(Throwable t){
		System.out.println(t);
		System.out.println("afterThrowing running......");
	}
	@Around("execution(* cn.itcast.aop.annotation.BookService.add(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("around before running......");
		Object retValue = pjp.proceed();
		System.out.println("around after running......");
		return retValue;
	}
}
</span>

注意:上述的配置與XML一一對應起來的話,就會簡單很多。