责任链模式在SpringAOP中的使用

当一个对象在一条链上被多个拦截器拦截处理时,我们这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景.

SpringAOP就是利用动态代理和责任链模式实现的,当一个切面有多个织入时,这些需要织入的方法就形成了一个责任链,就像Filter链一样。

下面就模拟一下springaop中的责任链:

接口:

public interface Joinpoint {
    Object proceed() throws Throwable;
}
public interface MethodInvocation extends Joinpoint {
}

定义拦截器接口

public interface MethodInterceptor {
    Object invoke(MethodInvocation mi) throws Throwable;
}

定义前置通知,在目标方便调用前执行通知:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor{
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        System.out.println("I am BeforeAdvice");
        return mi.proceed();
    }
}

定义后置通知,在目标方法完成后执行通知:

public class AspectJAfterAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        Object var;
        try {
            var = mi.proceed();
        }finally {
            System.out.println("I am AfterAdvice");
        }
        return var;
    }
}

中间类,拦截器链调用逻辑:

public class ReflectiveMethodInvocation  implements MethodInvocation{
    List<MethodInterceptor> methodInterceptors;

    public ReflectiveMethodInvocation(List<MethodInterceptor> methodInterceptors) {
        this.methodInterceptors = methodInterceptors;
    }

    private int index = -1;

    @Override
    public Object proceed() throws Throwable {
        Object var = null;
        if (index == this.methodInterceptors.size()-1) {
            System.out.println("真正的目标方法");
            return new String("ha");
        }else{
            var = methodInterceptors.get(++index).invoke(this);

        }

        return var;
    }

}

测试类:

public class Test {
    public static void main(String[] args) throws Throwable {
        AspectJAfterAdvice aspectJAfterAdvice = new AspectJAfterAdvice();
        MethodBeforeAdviceInterceptor methodBeforeAdviceInterceptor = new MethodBeforeAdviceInterceptor();
        List<MethodInterceptor> methodInterceptors = new ArrayList<>();
        methodInterceptors.add(methodBeforeAdviceInterceptor);
        methodInterceptors.add(aspectJAfterAdvice);

        ReflectiveMethodInvocation reflectiveMethodInvocation = new ReflectiveMethodInvocation(methodInterceptors);
        reflectiveMethodInvocation.proceed();
    }
}

执行结果

I am BeforeAdvice
真正的目标方法
I am AfterAdvice

下面是springAOP中的源码

首先看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;
    }
}

整个执行流程:

原创文章 317 获赞 416 访问量 112万+

猜你喜欢

转载自blog.csdn.net/u014082714/article/details/103463378