Spring之手寫Aop(3)
到了這裡也到了一個很重要的部分了,使用aop本質上是對方法使用之前,或之後新增自己的邏輯,而如何具體實現,有Aop聯盟就抽象出了方法攔截器,用來執行在方法之前或之後的邏輯,而如何來呼叫這些攔截器,攔截器的執行順序如何呢?這有引出了方法呼叫器(我自己取的, 也就是MethodInvocation)
首先來看一下方法攔截器的定義
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.aopalliance.intercept;
public interface MethodInterceptor extends Interceptor {
//委託方法呼叫器進行執行
Object invoke(MethodInvocation var1) throws Throwable;
}
根據執行的先後不同方法攔截器有各自的實現,其主要有3種,具體的實現如下
package com.autoproxy.Adapter;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* Created by zoujianglin
* 2018/8/28 0028.
*/
//前置攔截器,在方法之前被呼叫
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
private MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
if (advice == null) {
throw new IllegalArgumentException("advice is null");
}
this.advice = advice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
package com.autoproxy.Adapter;
import com.util.Assert;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* Created by zoujianglin
* 2018/8/29 0029.
*/
//後置攔截器,在方法返回之後呼叫
public class AfterReturningAdviceInterceptor implements MethodInterceptor {
private AfterReturningAdice advice;
public AfterReturningAdviceInterceptor(AfterReturningAdice methodAfterAdice) {
Assert.notNull(methodAfterAdice, "methodAfrerAdvice is null");
this.advice = methodAfterAdice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object returnValue = mi.proceed();
this.advice.after(mi.getMethod(), mi.getArguments(), mi.getThis());
return returnValue;
}
}
package com.autoproxy.Adapter;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* Created by zoujianglin
* 2018/8/29 0029.
*/
//異常攔截器 在方法丟擲異常後使用
public class ThrowsAdviceInterceptor implements MethodInterceptor {
private ThrowsAdvice throwsAdvice;
public ThrowsAdviceInterceptor(ThrowsAdvice throwsAdvice) {
this.throwsAdvice = throwsAdvice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object returnValue = null;
try {
returnValue = mi.proceed();
} catch (Throwable e) {
throwsAdvice.throwAdvice(mi.getMethod(), mi.getArguments(), mi.getThis(), e);
}
return returnValue;
}
}
方法攔截器 有方法呼叫器進行呼叫 接下來看一下方法呼叫器 其結構如下
public interface MethodInvocation extends Invocation {
//獲取被代理的方法
Method getMethod();
}
public interface Invocation extends Joinpoint {
//獲取呼叫方法的引數
Object[] getArguments();
}
public interface Joinpoint {
// 呼叫攔截器
Object proceed() throws Throwable;
//獲取被代理的物件
Object getThis();
AccessibleObject getStaticPart();
}
為了方便理解,我畫了一個結構圖,如下
下面看看我們主要類AopMethodInvocation是怎麼實現的
package com;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;
/**
* Created by zoujianglin
* 2018/8/28 0028.
*/
public class AopMethodInvocation implements MethodInvocation {
//控制攔截器偏移量
private int currentIndex = -1;
private List<MethodInterceptor> methodInterceptors;
//代理物件
private Object target;
//代理方法
private Method method;
//代理方法的引數
private Object[] arguments;
public AopMethodInvocation(Object target, Method method, Object[] arguments,
List<MethodInterceptor> methodInterceptors) {
this.methodInterceptors = methodInterceptors;
this.target = target;
this.method = method;
this.arguments = arguments;
}
public Method getMethod() {
return this.method;
}
public Object[] getArguments() {
return arguments;
}
//呼叫攔截器
public Object proceed() throws Throwable {
if (currentIndex == methodInterceptors.size() - 1) {
//呼叫原先方法 method.invoke(),可以通過引數獲得
//新增判斷 防止遞迴完後每個方法都回到這 也算終止條件
return method.invoke(target, arguments);
} else {
return methodInterceptors.get(++currentIndex).invoke(this);
}
}
public Object getThis() {
return this.target;
}
public AccessibleObject getStaticPart() {
return this.method;
}
public String toString() {
StringBuilder sb = new StringBuilder("ReflectiveMethodInvocation: ");
sb.append(this.method).append("; ");
if (this.target == null) {
sb.append("target is null");
} else {
sb.append("target is of class [").append(this.target.getClass().getName()).append(']');
}
return sb.toString();
}
}