美文网首页征服Spring
spring源码解析之AOP实现(六)

spring源码解析之AOP实现(六)

作者: binecy | 来源:发表于2019-03-18 17:00 被阅读0次

源码分析基于spring 4.3.x

这是我第三次看spring的源码了
思路清晰了很多,也对博客内容做了很多修改。

一个小栗子

定义一个服务接口

package com.spring.start.service;

public interface IBlogService {
    int getBlogCount();
}

接口实现类

package com.spring.start.service;

public class BlogService implements IBlogService {
    @Override
    public int getBlogCount() {
        int count = 123;
        System.out.println("blog count : " + count);
        return count;
    }
}

定义一个切面(Aspect)

@Aspect
public class LogAspect {

    @Around("execution(public * com.spring.start..*.*.*(..))")
    public Object methodAroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("log1 : start method");
        Object result = joinPoint.proceed(joinPoint.getArgs());
        System.out.println("log2 : end method");
        return result;
    }


    @Around("execution(public * com.spring.start..*.*.*(..))")
    public Object methodAroundLog2(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("log2 : start method");
        Object result = joinPoint.proceed(joinPoint.getArgs());
        System.out.println("log2 : end method");
        return result;
    }
}

切面类中定义了两个通知(Advice)methodAroundLog和methodAroundLog2,对com.spring.start下所有子包中所有类的所有pubic方法进行拦截,并输出写简单的log信息。

来看看配置文件application.xml

    <!-- 开启aop -->
    <aop:aspectj-autoproxy/>

    <!-- 定义切面 -->
    <bean id="logAspect" class="com.spring.start.aop.LogAspect"></bean>

    <!-- 定义service -->
    <bean id="blogService" class="com.spring.start.service.BlogService"></bean>

测试方法

public static void main(String[] args) {
    ApplicationContext beanFactory = new ClassPathXmlApplicationContext("application.xml");
    IBlogService blogService = beanFactory.getBean("blogService", IBlogService.class);
    blogService.getBlogCount();        
}

输出结果:

log1 : start method
log2 : start method
blog count : 123
log2 : end method
log2 : end method

可以看到aop已成功拦截到了方法,并输出了对应的log。

一开始,先明确几个概念
aspect:切面,一个切面可以包括多个切入点和通知,而且标签内部的通知和切入点定义是无序的
advice:通知,表示一个method执行前或执行后的动作。上面栗子中定义了两个环绕通知
pointcut:切入点,表示根据method的名字或者正则表达式去拦截一个method。
advisor:只有一个通知和一个切入点的切面,可以看做一种特殊的aspect。

开始阅读源码前,我比较关注的几个问题:

  1. <aop:aspectj-autoproxy/>的作用
  2. spring如何根据Aspect注解创建切面
  3. spring如何根据切面信息创建代理对象
  4. 上面定义的两个通知methodAroundLog和methodAroundLog2,spring是如何进行链式调用的

<aop:aspectj-autoproxy/> 的作用

aspectj-autoproxy是spring自定义的标签。我们知道,在spring中自定义标签,需要编写一个继承于NamespaceHandlerSupport的类来实现标签解析工作。
在spring源码中搜索一下,就可以发现aspectj-autoproxy的解析类是AopNamespaceHandler:

public void init() {
    this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
    this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

而AspectJAutoProxyBeanDefinitionParser类负责对aspectj-autoproxy标签进行解析:

public BeanDefinition parse(Element element, ParserContext parserContext) {
    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
    extendBeanDefinition(element, parserContext);
    return null;
}

这里AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary 会调用到AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

registerOrEscalateApcAsRequired就是把AnnotationAwareAspectJAutoProxyCreator注入到spring上下文环境中,

AnnotationAwareAspectJAutoProxyCreator是一个关键的类,继承了BeanPostProcessor接口,它负责创建切面。

创建advisor

来看看AbstractAutoProxyCreator.postProcessAfterInitialization

public Object postProcessAfterInitialization(Object bean, String beanName) ... {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

主要逻辑在wrapIfNecessary:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    ...
    
    // 创建Advices和Advisors
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理对象
        Object proxy = createProxy(bean.getClass(), 
                beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

getAdvicesAndAdvisorsForBean正是提供给子类创建通知的方法,该方法会调用子类AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean,再调用的它的findEligibleAdvisors方法

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 创建Advisors
    List<Advisor> candidateAdvisors = findCandidateAdvisors();  
    // 过滤Advisors
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);  
    // 扩充
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

这是一个非常重要的方法,实现了几个关键步骤

  1. findCandidateAdvisors 查找Advisors(第一次会创建)
  2. findAdvisorsThatCanApply 根据目标bean的class过滤一部分的Advisors
  3. extendAdvisors 扩充Advisors,spring会根据需要添加一些内部的Advisors
  4. sortAdvisors 对Advisors排序

findCandidateAdvisors 查找Advisors

findCandidateAdvisors方法负责找到所有的Advisors,该方法会调用到子类AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
    // 添加父类的advisors
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 1-aspectJAdvisorsBuilder.buildAspectJAdvisors
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

1-aspectJAdvisorsBuilder.buildAspectJAdvisors是创建Advisor的关键,来看看BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<Advisor>();
                aspectNames = new LinkedList<String>();
                // 获取所以的bean
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
                        
                for (String beanName : beanNames) {
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    // 如果有Aspect注解
                    if (this.advisorFactory.isAspect(beanType)) {   
                        aspectNames.add(beanName);
                        // 获取Aspect信息
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // 创建AspectInstanceFactory
                            MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);  
                            // 2-advisorFactory.getAdvisors
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            if (this.beanFactory.isSingleton(beanName)) {
                                this.advisorsCache.put(beanName, classAdvisors);    
                            }
                            else {
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            advisors.addAll(classAdvisors);
                        } else {
                            ...
                        }
                    }   
                }
            }
        }   
    }
    
    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    // 查询缓存 添加到结果
    ...
    return advisors;
}       

PerClauseKind是aspect的初始化模式,这里只展示了SINGLETON模式的创建, 可以参考 aspect api

这里可以看到一个简单的单例模式,如果当前的aspectBeanNames为null,会创建Advisors,并保存在advisorsCache中,以后每次都从advisorsCache取出advisors。

可以看到,如果一个类有Aspect注解,就会创建AspectInstanceFactory,并通过AspectJAdvisorFactory创建Advisors
2-advisorFactory.getAdvisors将会调用到ReflectiveAspectJAdvisorFactory.getAdvisors

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // 切面类
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();  
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    validate(aspectClass);
    
    // 使用装饰器LazySingletonAspectInstanceFactoryDecorator保证MetadataAwareAspectInstanceFactory只创建一次
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new LinkedList<Advisor>();
    for (Method method : getAdvisorMethods(aspectClass)) {  
        // 创建Advisor
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);  
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
    
    ...
    return advisors;
}   

getAdvisorMethods获取所有没有Pointcut注解的方法,有Pointcut注解的方法不可能是Advisor。

//  创建Advisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
        int declarationOrderInAspect, String aspectName) {
    ...
    // 获取切入点Pointcut    
    AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());      
    if (expressionPointcut == null) {
        return null;
    }
    
    // 创建Advisor,Advisor中包含了pointcut和adviceMethod
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}   

这里创建了InstantiationModelAwarePointcutAdvisorImpl(Advisor),该类中有拦截类declaringClass,拦截方法aspectJAdviceMethod等信息,最重要的是declaredPointcut(Pointcut)和instantiatedAdvice(Advice)。

先看看切入点Pointcut的创建

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 获取该方法的Before, Around, After, AfterReturning, AfterThrowing, Pointcut注解
    AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);        
    if (aspectJAnnotation == null) {
        return null;
    }

    // 生成AspectJExpressionPointcut,该类Expression属性记录了pointcut表达式
    AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    ajexp.setBeanFactory(this.beanFactory);
    return ajexp;
}   

Advice的创建需查看InstantiationModelAwarePointcutAdvisorImpl构造方法:

    public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        ...
        if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            ...
        }
        else {
            this.pointcut = this.declaredPointcut;
            this.lazy = false;
            this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        }
    }

instantiateAdvice调用了ReflectiveAspectJAdvisorFactory.getAdvice

    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        // 获取拦截类
        Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        validate(candidateAspectClass);
        // 获取拦截方法上的注解    
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }

        ...
        AbstractAspectJAdvice springAdvice;

        switch (aspectJAnnotation.getAnnotationType()) {
            case AtPointcut:
                // pointcut注解不处理
                return null;
            ...
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
        }
        ...
        return springAdvice;
    }

这里针对Around/Before/After/AfterReturning/AfterThrowing创建了对应的Advice。

findAdvisorsThatCanApply 过滤Advisors

findAdvisorsThatCanApply方法,会过滤部分的Advisors
这里会检查目标bean的class和class中是否有方法可以匹配Advisor,如果没有则过滤。代码比较繁琐,不展开了。

extendAdvisors(eligibleAdvisors) 扩充Advisors

看看AspectJAwareAdvisorAutoProxyCreator.extendAdvisors

protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary

public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    // Don't add advisors to an empty list; may indicate that proxying is just not required
    if (!advisors.isEmpty()) {
        ...
        if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
            // 添加ExposeInvocationInterceptor
            advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
            return true;
        }
    }
    return false;
}   

spring会在advisors 列表开始位置添加ExposeInvocationInterceptor。

创建代理对象

我们知道,spring通过动态代理类实现aop,有jdk动态代理和cglib两种方法。
如果要使用jdk动态代理,被代理类必须实现一个接口。
为了避免在这里额外介绍cglib,我在上面的小栗子中让spring生成的BlogService实现了一个接口,这样我们来看一下jdk动态代理如何实现aop。

这里来看看代理对象的创建过程AbstractAutoProxyCreator.createProxy(第三个参数就是Advices信息)

protected Object createProxy(
    Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // 存储Advisor
    for (Advisor advisor : advisors) {  
        proxyFactory.addAdvisor(advisor);
    }
    
    return proxyFactory.getProxy(getProxyClassLoader());
}           

buildAdvisors只是做一些检查,转换处理,如将Advices转换成Advisor。
proxyFactory.addAdvisor这里将Advisor添加到proxyFactory中,proxyFactory类似于一个上下文,存放着Advisor。

proxyFactory.getProxy到调用父类ProxyCreatorSupport.createAopProxy

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    // 3-createAopProxy
    return getAopProxyFactory().createAopProxy(this);
}

3-createAopProxy中参数是this,proxyFactory将自身作为参数,调用DefaultAopProxyFactory.createAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        ...
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

可以看到,spring会根据用户配置和目标bean是否有实现接口,来决定使用JdkDynamicAopProxy或ObjenesisCglibAopProxy

来看看JdkDynamicAopProxy.getProxy

public Object getProxy(ClassLoader classLoader) {
    ...
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // 构建代理对象
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);    
}

注意:Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)第三个参数是JdkDynamicAopProxy.this,JdkDynamicAopProxy实现了InvocationHandler。

链式调用

JdkDynamicAopProxy实现了InvocationHandler,看一下关键的invoke方法:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 获取所有拦截器
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    // 获取拦截链
    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    // 4-调用拦截链
    retVal = invocation.proceed();
}

this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass) 获取拦截器链,
它会从缓存中查询,缓存没有时通过DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice会创建调用链

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass) {

    ...
    for (Advisor advisor : config.getAdvisors()) {
        if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            // 检查class是否匹配
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {    
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                // 检查method 是否匹配
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {    
                    // 运行时检查
                    if (mm.isRuntime()) {
                        for (MethodInterceptor interceptor : interceptors) {    
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
    }

    return interceptorList;
}   

这里通过poingcut检查是否能使用Advice,这部分不深入。

registry.getInterceptors(advisor)将Advice转化为MethodInterceptor方法拦截器,DefaultAdvisorAdapterRegistry.getInterceptors:

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

DefaultAdvisorAdapterRegistry.adapters有三个

    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

它们会将MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice转化为MethodInterceptor(他们没有实现MethodInterceptor接口,其他Advice都实现了MethodInterceptor接口)

回到4-调用拦截链,ReflectiveMethodInvocation.proceed

public Object proceed() throws Throwable {
    // 是否到拦截器链尾了
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 
        return invokeJoinpoint();
    }
    
    // 获取下一个拦截器,currentInterceptorIndex初始值是-1
    Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 
    // 是否为动态拦截器
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {    
        ...
    }
    else {
        // 直接调用
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);  
    }
}

可以看到,proceed方法会获取下一个拦截器,并调用它们的invoke方法。
注意,invoke会将ReflectiveMethodInvocation自身作为参数。

调用链以ExposeInvocationInterceptor开头,ExposeInvocationInterceptor只是简单的配置和恢复上下文

public Object invoke(MethodInvocation mi) throws Throwable {
    MethodInvocation oldInvocation = invocation.get();
    // 设置上下文
    invocation.set(mi); 
    try {
        return mi.proceed();
    }
    finally {
        invocation.set(oldInvocation);  // 恢复上下文
    }
}

mi.proceed()会重新调用到ReflectiveMethodInvocation.proceed(),然后调用到下一个拦截器。

看看AspectJAroundAdvice的实现

public Object invoke(MethodInvocation mi) throws Throwable {
    ...
    ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    // MethodInvocation转化为ProceedingJoin
    ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);    
    JoinPointMatch jpm = getJoinPointMatch(pmi);
    return invokeAdviceMethod(pjp, jpm, null, null);
}

protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t) throws Throwable {
    // argBinding绑定参数
    return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));    
}

protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {
    ...
    int numBound = 0;

    if (this.joinPointArgumentIndex != -1) {
        adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
    }
    ...
    return adviceInvocationArgs;
}

argBinding负责绑定参数,会把JoinPoint作为通知方法的第一个参数。
invokeAdviceMethodWithGivenArgs会调用到aspectJAdviceMethod.invoke,就是执行Around通知。

在环绕通知中

    @Around("...")
    public Object methodAroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed(joinPoint.getArgs());
        return result;
    }

由于第一个参数就是JoinPoint,所以joinPoint.proceed(joinPoint.getArgs());`就可以调用下一个拦截器,这样才能继续调用拦截器链。

Before通知会调用MethodBeforeAdviceInterceptor

    public Object invoke(MethodInvocation mi) throws Throwable {
        // 调用before通知
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        // 继续调用拦截器链
        return mi.proceed();  
    }

After通知会调用AspectJAfterThrowingAdvice

    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();  // 先调用拦截器链
        }
        catch (Throwable ex) {
            if (shouldInvokeOnThrowing(ex)) {
                // 调用after通知
                invokeAdviceMethod(getJoinPointMatch(), null, ex);          
            }
            throw ex;
        }
    }

到这里,spring aop的源码解析就完成了。
这部分还是挺复杂的,需要耐心点看源码。

相关文章

网友评论

    本文标题:spring源码解析之AOP实现(六)

    本文链接:https://www.haomeiwen.com/subject/lxlgpqtx.html