一 Aop责任链
如何理解责任链呢?当一个切面有多个织入时,这些需要织入的方法就形成了一个责任链,就像Filter链一样
二 原理
看了上图我们理解一下,责任链中包含每一个Handler,那每个Hanlder在执行之后,程序是怎么知道下次要执行哪个Handler呢?我们先做出假设,每个Handler中存储着NextHandler,这样程序就知道下次执行哪个了
三 责任链实现
3.1 BaseHandler
首先我们创建一个BaseHandler类
package com.example.proxy.chain;
/**
* BaseHandler class
*
* @author TransientBa
* @date 2018/3/10
*/
public abstract class BaseHandler {
/**
* 用来存储下一个Handler
*/
private BaseHandler nextHandler;
public BaseHandler getNextHandler() {
return nextHandler;
}
public void setNextHandler(BaseHandler nextHandler) {
this.nextHandler = nextHandler;
}
/** 如果nextHandler不为空 则执行下一个Handler**/
public void execute(){
handlerProcess();
if( nextHandler != null){
nextHandler.execute();
}
}
/**
* Handler
* @return void
*/
protected abstract void handlerProcess();
}
依据我们上面的假设,类中有一个nextHandler属性,我们假设他用来保存下一个Handler。
还有一个抽象方法handlerProcess(),此方法用来被继承后写执行过程。
最后在execute()中我们先执行本次Handler中的handlerProcess,然后判断NextHandler是否为空,如果不为空。则执行NextHandler也就是下一个Handler的方法。
3.2 Client测试
在这个类中我们首先创建三个Handler来继承上面的BaseHandler类,重写其中的handlerProcess方法
,然后在实例化三个雷,并将它们按照顺序赋值给各自的NextHandler,然后我们执行一下
package com.example.proxy.chain;
/**
* Client class
*
* @author TransientBa
* @date 2018/3/12
*/
public class Client {
/**创建ABC三个Handler来继承BaseHandler**/
static class HandlerA extends BaseHandler{
@Override
protected void handlerProcess() {
System.out.println("handle by a");
}
}
static class HandlerB extends BaseHandler{
@Override
protected void handlerProcess() {
System.out.println("handle by b");
}
}
static class HandlerC extends BaseHandler{
@Override
protected void handlerProcess() {
System.out.println("handle by c");
}
}
public static void main(String[] args) {
BaseHandler handlerA = new HandlerA();
BaseHandler handlerB = new HandlerB();
BaseHandler handlerC = new HandlerC();
/**
* 将下个Handler赋值给当前Handler中的NextHandler属性
* 有点像HashMap中的Node 每个Node存储着下一个Node
*/
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
handlerA.execute();
}
}
执行结果
3.3 优化
看到这里是不是已经发现了问题所在,这样虽然实现了整个链式的调用,但当我们实例化三个Handler后,需要手动的将每个Handler之前的关系表明,也就是赋值NextHandler,这样很麻烦,实现起来也不现实。那我们如何改进呢?
3.4 Chain
这里创建一个chain类,这个类用来做什么呢?我们将上面的BaseHandler类拆分为ChainBaseHandler类和Chain类两个类来实现链式调用
package com.example.proxy.chain;
import java.util.List;
/**
* Chain class
*
* @author TransientBa
* @date 2018/3/12
*/
public class Chain {
private List<ChainBaseHandler> handlers;
/**
* 用来表示handlers的游标
*/
private int index = -1;
public Chain(List<ChainBaseHandler> handlers){
this.handlers = handlers;
}
/**
* 通过index自增 调用excute实现递归 遍历整个handlers
*/
public void proceed(){
if(index == handlers.size() - 1){
return;
}
handlers.get(++index).execute(this);
}
}
可以看到,在chain中我们取消了NextHandler属性,而是改用了一个List,类型是ChainBaseHandler,
还多了一个index,初始值为-1,
然后是一个构造,在实例化时要传入一个List进来,并赋值给该类的handlers属性,
最后是proceed方法,在这个方法中我们首先判断了index是否超过List的size,如果超过了则返回,如果没操作,就得到当索引的Handler,然后执行ChainBaseHandler中的execute方法
3.5 ChainBaseHandler
在这个类中我们只有两个方法,execute和handlerProcess,其中handlerProcess依然用来被继承后写执行过程。
execute方法有一个参数Chain,这个方法首先进来会执行当前Handler的HandlerProcess执行过程,然后会调用传入Chain的proceed方法,这样调用就又回到了proceed中,继续判断index并开始下一次循环
package com.example.proxy.chain;
/**
* ChainBaseHandler class
*
* @author TransientBa
* @date 2018/3/12
*/
public abstract class ChainBaseHandler {
/**同样先执行自己的动作 再调用chain的proceed去遍历下一个Handler**/
public void execute(Chain chain){
handlerProcess();
chain.proceed();
};
protected abstract void handlerProcess();
}
3.6ChainClient测试
package com.example.proxy.chain;
import java.util.Arrays;
import java.util.List;
/**
* ChainClient class
*
* @author TransientBa
* @date 2018/3/12
*/
public class ChainClient {
static class ChainHandlerA extends ChainBaseHandler{
@Override
protected void handlerProcess() {
System.out.println("handler by chain a");
}
}
static class ChainHandlerB extends ChainBaseHandler{
@Override
protected void handlerProcess() {
System.out.println("handler by chain b");
}
}
static class ChainHandlerC extends ChainBaseHandler{
@Override
protected void handlerProcess() {
System.out.println("handler by chain c");
}
}
public static void main(String[] args) {
/**
* 声明HandlerList关系链 通过数组顺序排序
* 不再像之前那样手动给当前Handler中的NextHandler设置值
* 同样每个chain中间没有相互的依赖 实现解耦
*/
List<ChainBaseHandler> handlerList = Arrays.asList(
new ChainHandlerA(),
new ChainHandlerB(),
new ChainHandlerC()
);
Chain chain = new Chain(handlerList);
chain.proceed();
}
}
在这个类中我们同样先创建三个类继承ChainBaseHandler,重写handlerProcess方法,
然后用Arrays.asList来初始一个handlerList,并传入Chain的构造,实例化出来一个Chain,调用proceed方法开始遍历,
执行一下:
四 ReflectiveMethodInvocation
上面我们用代码模拟了Aop的责任链,接下来我们看看源码中Aop责任链是如何实现的,该类位于org.springframework.aop.framework下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.aop.framework;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.lang.Nullable;
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
protected final Object proxy;
@Nullable
protected final Object target;
protected final Method method;
protected Object[] arguments = new Object[0];
@Nullable
private final Class<?> targetClass;
@Nullable
private Map<String, Object> userAttributes;
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
public final Object getProxy() {
return this.proxy;
}
@Nullable
public final Object getThis() {
return this.target;
}
public final AccessibleObject getStaticPart() {
return this.method;
}
public final Method getMethod() {
return this.method;
}
public final Object[] getArguments() {
return this.arguments;
}
public void setArguments(Object... arguments) {
this.arguments = arguments;
}
@Nullable
public Object proceed() throws Throwable {
if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
@Nullable
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
public MethodInvocation invocableClone() {
Object[] cloneArguments = this.arguments;
if(this.arguments.length > 0) {
cloneArguments = new Object[this.arguments.length];
System.arraycopy(this.arguments, 0, cloneArguments, 0, this.arguments.length);
}
return this.invocableClone(cloneArguments);
}
public MethodInvocation invocableClone(Object... arguments) {
if(this.userAttributes == null) {
this.userAttributes = new HashMap();
}
try {
ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation)this.clone();
clone.arguments = arguments;
return clone;
} catch (CloneNotSupportedException var3) {
throw new IllegalStateException("Should be able to clone object of type [" + this.getClass() + "]: " + var3);
}
}
public void setUserAttribute(String key, @Nullable Object value) {
if(value != null) {
if(this.userAttributes == null) {
this.userAttributes = new HashMap();
}
this.userAttributes.put(key, value);
} else if(this.userAttributes != null) {
this.userAttributes.remove(key);
}
}
@Nullable
public Object getUserAttribute(String key) {
return this.userAttributes != null?this.userAttributes.get(key):null;
}
public Map<String, Object> getUserAttributes() {
if(this.userAttributes == null) {
this.userAttributes = new HashMap();
}
return this.userAttributes;
}
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();
}
}
可以看到该类首先同样定义了index
private int currentInterceptorIndex = -1;
也定义了List<>和其他的一些参宿
protected final List<?> interceptorsAndDynamicMethodMatchers;
我们着重看下proceed()方法
@Nullable
public Object proceed() throws Throwable {
//上面定义了从-1开始 此处判断index是否超过List该循环的长度
if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
//自增后拿到当前循环的interceptorOrInterceptionAdvice
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//判断类型执行invoke或proceed
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
五 总结
责任链模式解决了请求和处理类耦合在一起的情况,用一系列的类形成一个链去处理,使得在链中的每个类都有机会去处理该请求,同样反过来说,对于链中每个类自己的动作都是高内聚的,即使拆分或剔除出去也不会影响其他的动作。