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();
}
}