Spring 5 源码解析- AOP原理分析-5

这里以

配置文件(UserAOPTest-context.xml)信息:

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    class="org.springframework.context.support.learning.aop.UserImpl"/>

    class="org.springframework.context.support.learning.aop.UserAspect"/>

    class="false"/>

View Code

测试用例代码:

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
public class UserAOPTest {

    @Test
    void aopTestWithJDK(){
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(getClass(), "UserAOPTest-context.xml");

        User user = ctx.getBean(User.class);
        user.doTask();
    }
}

View Code

代码:User

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
public interface User {

    String doTask();

}

View Code

代码:UserImpl

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
public class UserImpl implements User{

    @Override
    public String doTask() {
        System.out.println(getClass().toString() + " doTask...");
        return "return doTask";
    }
}

View Code

代码:UserAspect

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
@Aspect
public class UserAspect {

    /** Logger used by this class. Available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());

    @Pointcut("execution(public * org.springframework.context.support.learning.aop.User.doTask(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void before(JoinPoint point) throws Throwable {
        Signature signature = point.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("before --> begin Time:" + System.currentTimeMillis());
        }
    }

    @After("pointCut()")
    public void after(JoinPoint point) throws Throwable {
        Signature signature = point.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("after --> begin Time:" + System.currentTimeMillis());
        }
    }

    @AfterReturning(pointcut="pointCut()", returning="returnValue")
    public void afterReturning(JoinPoint point, Object returnValue) throws Throwable {
        Signature signature = point.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("afterReturning --> begin Time:" + System.currentTimeMillis());
        }
    }

    @Around("pointCut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        Signature signature = pjp.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("around --> begin Time:" + System.currentTimeMillis());
        }
        pjp.proceed();
        if (logger.isInfoEnabled()) {
            logger.info("around --> end Time:" + System.currentTimeMillis());
        }
    }

    @AfterThrowing(throwing="ex", pointcut="pointCut()")
    public void afterThrowing(Throwable ex) {
        if (logger.isInfoEnabled()) {
            logger.info("目标方法中抛出的异常:" + ex);
            logger.info("afterThrowing --> end Time:" + System.currentTimeMillis());
        }
    }

}

View Code

一.读取AOP配置,并根据AOP配置进心初始化

XmlBeanDefinitionReader#registerBeanDefinitions()
XmlBeanDefinitionReader#createReaderContext()
XmlBeanDefinitionReader#getNamespaceHandlerResolver()
XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver()

1.读取XML配置文件时,创建默认 DefaultNamespaceHandlerResolver 实例,准备解析XML配置文件信息。

  1. 依次循环解析

(在 DefaultNamespaceHandlerResolver#getHandlerMappings() 中读取META-INF/spring.handlers配置文件。)

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

  1. 具体解析器进行处理。
    BeanDefinitionParserDelegate#parseCustomElement(Element, BeanDefinition)
    Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
/**
     * Parse a custom element (outside of the default namespace).

     * @param ele the element to parse
     * @param containingBd the containing bean definition (if any)
     * @return the resulting bean definition
     */
    @Nullable
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        String namespaceUri = getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        }
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

View Code

  1. 解析器初始化。

AopNamespaceHandler#init()

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
public class AopNamespaceHandler extends NamespaceHandlerSupport {

    /**
     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
     * and '{@code scoped-proxy}' tags.

     */
    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.5+ XSDs
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace in 2.5+
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}

View Code

  1. 具体配置依次分析:

ConfigBeanDefinitionParser

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
returning="returnValue">

                                throwing="ex">

View Code

AspectJAutoProxyBeanDefinitionParser

AspectJAutoProxyBeanDefinitionParser#parse
AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)
registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source)

ScopedProxyBeanDefinitionDecorator

二. AOP创建AnnotationAwareAspectJAutoProxyCreator 实例

PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

循环注册 BeanPostProcessors 时,创建 AnnotationAwareAspectJAutoProxyCreator 实例,并添加到 BeanPostProcessor 列表。

AnnotationAwareAspectJAutoProxyCreator 实例初始化时,初始化,创建后期使用的辅助对象实例。

AnnotationAwareAspectJAutoProxyCreator#initBeanFactory()

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
if (this.aspectJAdvisorFactory == null) {
    this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
        new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);

View Code

三. 创建业务类实例,并根据切点配置创建代理对象

(一) 创建切面通知(Advice)实例 Advisor。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation()
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation()
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip()
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors()
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors()

在创建对象实例之前,解析当前程序 @Aspect 标记的类信息 {Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}。

  1. 获得当前 beanFactory 中配置的所有 beanNames 信息。

BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false)

  1. 循环遍历处理 bean 配置。

a. 获得 beanName 对应的类型。

b. 判断 beanType 是否是 isAspect(beanType)。

c. 获取 beanName 对应的所有通知 ( Advice ) 包装列表 List

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors()
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisorMethods()

  1. 获取 aspectClass 所有方法(Method),并按 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 进行排序。

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor(Method, MetadataAwareAspectInstanceFactory , int , String)

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
@Override
    @Nullable
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {

        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }

        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

View Code

1.创建方法切点信息实例。AspectJExpressionPointcut

  1. 创建通知和切点关联对象实例。 InstantiationModelAwarePointcutAdvisorImpl

  2. 最终保存在 org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#advisorsCache 实例中。

InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice()

ReflectiveAspectJAdvisorFactory#getAdvice()

(二). 创建bean 代理对象

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition ,Object[] )
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance(String, RootBeanDefinition, Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(String, RootBeanDefinition, BeanWrapper)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object, String)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(@Nullable, String)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary(Object bean, String beanName, Object cacheKey)

  1. 检查是否是 AOP 相关的配置或工具类。

  2. 检查是否 满足AOP代理条件。

  3. 获取满足条件的通知(advice)。 目标类中,只要有一个方法满足 切入点(Pointcut)条件,就将通知(advice)添加到代理类拦截器中。

  4. 创建AOP代理实例。

    Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
/**
     * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.

     * @param bean the raw bean instance
     * @param beanName the name of the bean
     * @param cacheKey the cache key for metadata access
     * @return a proxy wrapping the bean, or the raw bean instance as-is
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.

        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;
    }

View Code

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy(Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)
org.springframework.aop.framework.ProxyProcessorSupport#evaluateProxyInterfaces(Class, ProxyFactory)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors(String beanName, Object[] specificInterceptors)
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)

  1. 遍历目标类所有接口。

  2. 处理满足条件的通知和公共通知。

  3. 通过代理工厂类,创建代理类。

    Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
/**
     * Create an AOP proxy for the given bean.

     * @param beanClass the class of the bean
     * @param beanName the name of the bean
     * @param specificInterceptors the set of interceptors that is
     * specific to this bean (may be empty, but not null)
     * @param targetSource the TargetSource for the proxy,
     * already pre-configured to access the bean
     * @return the AOP proxy for the bean
     * @see #buildAdvisors
     */
    protected Object createProxy(Class beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {

        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        // Use original ClassLoader if bean class not locally loaded in overriding class loader
        ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
            classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
        }
        return proxyFactory.getProxy(classLoader);
    }

View Code

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy(Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy()
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy()
org.springframework.aop.framework.AopProxy#getProxy(java.lang.ClassLoader)

  1. 创建 AopProxy 代理实例。这里区分 JDK动态代理(JdkDynamicAopProxy) 和 Cglib 代理(ObjenesisCglibAopProxy)。
    Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
@Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!NativeDetector.inNativeImage() &&
                (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }

View Code

  1. 使用 AopProxy 代理创建最终的代理类。区别两种代理情况。

AopProxy 创建代理类实例:

JDK 生成动态代理简单,直接调用JDK的方法生成。org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
@Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
    }

View Code

JdkDynamic 生成的代理类:

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
package com.sun.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.springframework.context.support.learning.aop.User;

public final class $Proxy35 extends Proxy implements User {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy35(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String doTask() throws  {
        try {
            return (String)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("org.springframework.context.support.learning.aop.User").getMethod("doTask");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

View Code

Cglib生成代理类,使用ASM字节码,稍微复杂些。 org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
@Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
        }

        try {
            Class rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class proxySuperClass = rootClass;
            if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                proxySuperClass = rootClass.getSuperclass();
                Class[] additionalInterfaces = rootClass.getInterfaces();
                for (Class additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.

            validateClassIfNecessary(proxySuperClass, classLoader);

            // Configure CGLIB Enhancer...

            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

            Callback[] callbacks = getCallbacks(rootClass);
            Class[] types = new Class[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // Generate the proxy class and create a proxy instance.

            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

View Code

Cglib 生成的代理类太复杂,这里就不展示。

四. 通过代理类实例调用业务方法和增强通知(Advice)

JdkDynamic代理:

org.springframework.aop.framework.JdkDynamicAopProxy#invoke(Object proxy, Method method, Object[] args)

  1. 获得当前方法的 所有通知(Advice) /拦截器。获取后,缓存中放一份。

  2. 如果没找到满足条件的通知(Advice),则直接调用实际方法。AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse)

  3. 通过目标方法,方法参数,通知(Advice) 创建调用方法的 ReflectiveMethodInvocation 实例。

  4. 调用 ReflectiveMethodInvocation#proceed()。 这个方法会轮询调用 通知(Advice) ,并最终调用实际的方法。

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed

Spring 5 源码解析- AOP原理分析-5Spring 5 源码解析- AOP原理分析-5
@Override
    @Nullable
    public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.

        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.

            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, 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);
        }
    }

View Code

(代理类实例)user.doTask() -> JdkDynamicAopProxy#invoke()

-> ReflectiveMethodInvocation#proceed() -> ExposeInvocationInterceptor#invoke(MethodInvocation mi)

AspectJAroundAdvice#invoke(MethodInvocation mi)

MethodBeforeAdviceInterceptor#invoke(MethodInvocation mi)

AspectJAfterAdvice#invoke(MethodInvocation mi)

AfterReturningAdviceInterceptor#invoke(MethodInvocation mi)

AspectJAfterThrowingAdvice#invoke(MethodInvocation mi)

AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments)

Cglib代理:

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept

  1. 获得当前方法的 所有通知(Advice) /拦截器。缓存中放一份。

  2. 如果没找到满足条件的通知(Advice),则直接调用代理方法。org.springframework.cglib.proxy.MethodProxy#invoke(Object obj, Object[] args)

  3. 通过目标方法,方法参数,通知(Advice) 创建调用方法的 CglibMethodInvocation 实例。 CglibMethodInvocation 是 ReflectiveMethodInvocation 子类。

  4. 调用 CglibMethodInvocation#proceed()。 这个方法会轮询调用 通知(Advice) ,并最终调用实际的方法。这个和JdkDynamic 类似 。

Original: https://www.cnblogs.com/StreamPlume/p/16023150.html
Author: 流羽
Title: Spring 5 源码解析- AOP原理分析-5

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574106/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球