以下是以項目的的形式就行運行驗證五個消息的運行順序及調用鏈的原理,裡面主要用到了遞歸調用。 本篇博客先給大家展示代碼,後面進行文字及圖片講解執行的順序 一、創建java項目springAOPModule 二、創建項目包結構如下: 三、創建目標方法UserService 四、創建執行介面及方法(Met ...
以下是以項目的的形式就行運行驗證五個消息的運行順序及調用鏈的原理,裡面主要用到了遞歸調用。
本篇博客先給大家展示代碼,後面進行文字及圖片講解執行的順序
一、創建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/