1. 程式人生 > >Spring之手寫Aop(3)

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

}

}