以下是以項目的的形式就行運行驗證五個消息的運行順序及調用鏈的原理,里面主要用到了遞歸調用。
本篇博客先給大家展示代碼,后面進行文字及圖片講解執行的順序
一、創建java項目springAOPModule
二、創建項目包結構如下:

三、創建目標方法UserService
/**
* 目標調用類
*/
public class UserService {
public void login(String userName,Integer age){
System.out.println("姓名為:"+userName+",年齡為:"+age);
}
}
四、創建執行接口及方法(MethodInvocation/DefaultMethodInvacation)
1、方法執行接口:MethodInvocation
/**
* 方法執行接口
*/
public interface MethodInvocation {
Object process() throws InvocationTargetException, IllegalAccessException;
}
2、 方法執行實習類:DefaultMethodInvacation
/**
* 執行方法實現類
*/
public class DefaultMethodInvacation implements MethodInvocation {
//5個通知集合
private List<MethodInterceptor> chian;
//目標對象
private Object target;
private Method method;// 目標方法
private Object args[];// 目標參數
int currentChianIndex;// 記錄當前攔截器鏈調用指針
public DefaultMethodInvacation(List<MethodInterceptor> chian, Object target, Method method, Object[] args) {
this.chian = chian;
this.target = target;
this.method = method;
this.args = args;
}
@Override
public Object process() throws InvocationTargetException, IllegalAccessException {
if(currentChianIndex==chian.size()){
return method.invoke(target,args);
}
MethodInterceptor methodInterceptor = chian.get(currentChianIndex++);
return methodInterceptor.invoke(this);
}
}
五、創建攔截接口及方法
1、目標方法攔截接口:MethodInterceptor
/**
* 創建方法攔截接口
*/
public interface MethodInterceptor {
//執行通知的攔截
Object invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException;
}
2、前置通知方法
/**
* 前置方法
*/
public class BeforInterceptorImpl implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
System.out.println("進入前置通知");
return methodInvocation.process();
}
}
3、后置通知方法
public class AfterMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInterceptor) throws InvocationTargetException, IllegalAccessException {
Object process = methodInterceptor.process();
System.out.println("后置通知");
return process;
}
}
4、環繞通知方法
public class AroundMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
System.out.println("環繞通知之前執行....");
Object process = methodInvocation.process();
System.out.println("環繞通知之后執行....");
return process;
}
}
六、創建測試方法execute
public class execute {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<MethodInterceptor> list = new ArrayList<>();
list.add(new BeforInterceptorImpl());
list.add(new AfterMethodInterceptor());
list.add(new AroundMethodInterceptor());
UserService userService = new UserService();
Method logingMethod = UserService.class.getMethod("login",String.class,Integer.class);
Object[] objects ={"cyb",25};
new DefaultMethodInvacation(list,userService,logingMethod,objects).process();
}
}
七、運行效果:

八、運行步驟原理解析:
啟動運行時,系統運行步驟如下:
1、將前置通知、后置通知、環繞通知3個攔截方法放入集合中
2、獲取目標方法
3、創建目標方法中的參數
4、通過有參構造方法將攔截方法集合、目標方法和參數傳遞到執行方法中並調用process處理方法
5、在process方法中,第一次獲取攔截方法中第一個前置通知,並在里面繼續調用process方法,此時index下標為1,獲取后置攔截方法,並在該方法中繼續調用process,此時又獲取的是環繞通知攔截方法,再次進入環繞通知方法,打印”環繞通知之前執行。。。”語句,此時index值為:3,再次調用process方法,此時index等於集合長度,調用模板方法,則打印目標方法語句。調完后繼續打印環繞方法的”環繞通知之后執行。。。”,執行完后在方法繼續返回到后置方法執行打印“后置通知”語句
九、圖形講解

注意:前置方法的打印要寫在方法調用之前,后置方法打印要寫在調用方法之后,環繞方法打印則分別寫在調用方法前后。
以上是本人對spring aop5個通知調用鏈原理的講解,大家理解后可以對這進行更好的優化,若上文有不合適的歡迎各位博友討論。轉發請說明出處,本人博客主頁地址為:https://home.cnblogs.com/u/chenyuanbo/
