Spring Aop原理分析(二) - Aop的拦截器和通知

其实当我们访问代理对象(也就是Spring Aop原理分析(一)最后所说的Bean)到最后访问目标方法,JdkDynamicAopProxy和CglibAopProxy采用了两种不同的方式:

  1. Proxy.newProxyInstance()->JdkDynamicAopProxy(继承InvocationHandler接口).invoke(),然后匹配通知类型调用通知(通知就是@Before、@After等等),最后调用目标方法
  2. Enhancer.Callback,Callback类似于InvocationHandler,类DynamicAdvisedInterceptor继承了Callback,它的intercept()方法就类似于invoke(),然后匹配通知类型调用通知,最后调用目标方法

Aop拦截器

这里写图片描述
对通知和目标方法的增强就是在invoke和intercept方法中,其中有段代码很重要:

//获得通知链,然后把它初始化到ReflectiveMethodInvocation中
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

关于通知的实现部分,我们放到后面再分析
这儿还需要多分析一点,在该方法中的类MethodMatcher,就是Pointcut(切入点)实现的一部分,MethodMatcher.matches检查该方法是否织入了Aop

接着看ReflectiveMethodInvocation.proceed (),类ReflectiveMethodInvocation的基类就是Joinpoint,在上面这张图中也很好的表现出了连接点的作用,继续看proceed的源码:

    public Object proceed() throws Throwable {
        //  如果通知链中的通知迭代调用完毕,这开始调用target函数,这个函数是通过反射机制完成的
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // 对通知进行动态匹配的判断
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

在这里我们看到对advice通知的调用入口了,我们继续看通知的实现部分

Aop通知

承上,想从源码角度去分析通知,有两个入口:

  1. Spring Aop原理分析(一)中提到的AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean()方法
  2. 上文提到的源码,调用路径
    this.advised.getInterceptorsAndDynamicInterceptionAdvice->DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice->DefaultAdvisorChainFactory.getInterceptors

在分析Aop的通知之前,我们先复习一下适配器模式:适配器模式

适配器定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配儿无法在一起工作的两个类能够在一起工作

下面我们看下适配器类图:
这里写图片描述

Advice(通知)中就使用了适配器模式,因为Spring需要将每个Advice(通知)都封装成对应的拦截器类型,在ReflectiveMethodInvocation.proceed ()方法中会调用MethodInterceptor.invoke()方法,目的是当有多个Advice时,通过这种方式可以很好地回调,所以需要使用适配器模式对Advice进行转换

下面我们看看具体代码

Advice接口:Adaptee

这里写图片描述

public interface MethodBeforeAdvice extends BeforeAdvice {
    void before(Method method, Object[] args, Object target) throws Throwable;

}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }

}

从类图和源码可知MethodInterceptor对Advice进行了封装了,再看它的invoke()方法,就已经和前面在ReflectiveMethodInvocation.proceed ()分析中联系起来了,可得ReflectiveMethodInvocation.proceed ()->MethodInterceptor.invoke()->ReflectiveMethodInvocation.proceed ()……循环调用,直到全部通知执行完毕,其他Advice的实现原理类似

Adapter接口:Target

public interface AdvisorAdapter {

    boolean supportsAdvice(Advice advice);

    MethodInterceptor getInterceptor(Advisor advisor);

}

MethodBeforeAdviceAdapter类……:Adapter

这里写图片描述
从类层次关系可以看出,有三种通知适配器,以类MethodBeforeAdviceAdapter为例:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

getInterceptor()方法返回的是MethodInterceptor(Adaptee)

DefaultAdvisorAdapterRegistry类:Client

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);


    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }


    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
        Advice advice = advisor.getAdvice();
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            if (adapter.supportsAdvice(advice)) {
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }
        if (interceptors.isEmpty()) {
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
    }

    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值