一,什么是责任链模式:
责任链模式是一种设计模式。在责任链模式里,很多处理器对象由每一个处理器对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个处理器决定处理此请求。
发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
责任链模式实现了请求者和处理者的解耦。
二,责任链模式的两个角色:
责任链模式涉及到的角色如下所示:
● 抽象处理者角色 :
定义出一个处理请求的接口。接口定义一个方法,用来设定和返回对下一个处理器对象的引用。
● 具体处理者角色 :
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。
三,Spring的AOP中的责任链模式:
当一个对象在一条链上被多个拦截器拦截处理时,我们这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景.
SpringAOP就是利用动态代理和责任链模式实现的,
当一个切入点(目标方法)有多个通知要织入时,这些需要织入的advice通知就形成了一个责任链。
下面就模拟一下spring aop中的责任链,将多个Advice通知织入一个目标方法:
四,模拟AOP中的责任链:
目标接口:
public interface ITargetService {
void targetMethod(); //目标方法--切入点
}
目标类:
@Service
public class TargetServiceImpl implements ITargetService {
/**
* 目标方法,切入点
*/
@Override
public void targetMethod() {
System.out.println("具体业务方法,正在执行具体业务逻辑...");
}
}
定义一个Advice接口,规范各个advice通知:
public interface IMyInterceptor {
void adviceMethod(ITargetService targetService);
}
前置通知(拦截器1)
@Service
public class BeforeInterceptorImpl implements IMyInterceptor {
/**
* 前置通知的方法
* @param targetService
*/
@Override
public void adviceMethod(ITargetService targetService) {
System.out.println("执行前置通知...");
//调用执行目标方法的业务逻辑:
targetService.targetMethod();
}
}
后置通知(拦截器2)
@Service
public class AfterInterceptorImpl implements IMyInterceptor {
/**
* 后置通知的方法
* @param targetService
*/
@Override
public void adviceMethod(ITargetService targetService) {
//调用执行目标方法的业务逻辑:
targetService.targetMethod();
System.out.println("执行后置通知...");
}
}
将多个通知织入目标方法:
改造目标方法targetMethod,将多个通知织入目标方法,并以责任链模式的方式进行织入:
@Service
public class TargetServiceImpl implements ITargetService {
private List<IMyInterceptor> myInterceptorList; //拦截器集合,即拦截器链
//实例化目标类对象的时候,注入属性满足依赖;
public TargetServiceImpl(List<IMyInterceptor> myInterceptorList) {
this.myInterceptorList = myInterceptorList;
}
private int currentInterceptorIndex = -1; //该指针驱动责任链条向前执行
/**
* 目标方法,切入点
*/
@Override
public void targetMethod() {
if (currentInterceptorIndex == this.myInterceptorList.size() - 1) {
System.out.println("具体业务方法,正在执行具体业务逻辑...");
return;
}
//获取拦截器链中当前的拦截器
IMyInterceptor myInterceptor = this.myInterceptorList.get(++this.currentInterceptorIndex);
//执行当前拦截器的Advice通知:
myInterceptor.adviceMethod(this);
}
public TargetServiceImpl() { }
}
五,补充:AOP源码:
首先看JdkDynamicAopProxy类中的invoke方法:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
Integer var10;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
Boolean var20 = this.equals(args[0]);
return var20;
}
if (this.hashCodeDefined || !AopUtils.isHashCodeMethod(method)) {
if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var18 = AopProxyUtils.ultimateTargetClass(this.advised);
return var18;
}
Object retVal;
if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
}
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
Object var13 = retVal;
return var13;
}
var10 = this.hashCode();
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var10;
}
看其中的这里:
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
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;
//调用拦截器的执行方法,拦截器执行拦截逻辑后继续调用目标方法的proceed()方法,参考下面的两个拦截器invoke()实现
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
before advice(前置通知)方法拦截器:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
after advice(后置通知)方法拦截器:
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object var2;
try {
var2 = mi.proceed();
} finally {
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
}
return var2;
}
public boolean isBeforeAdvice() {
return false;
}
public boolean isAfterAdvice() {
return true;
}
}