按照自己的思路去研究Spring AOP源码【1】
阅读原文时间:2021年04月29日阅读:1

目录

一个例子

// 定义一个切面
package cn.eagle.li.source.aspect;

@Component
@Aspect
public class ServiceAspect {
    @Pointcut("execution(* cn.eagle.li.source.service.*.*(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void methodBefore() {
        System.out.println("===== Before =====");
    }

    @After("pointCut()")
    public void methodAfter() {
        System.out.println("===== After =====");
    }

    @AfterReturning("pointCut()")
    public void methodReturn() {
        System.out.println("===== AfterReturning =====");
    }

    @Around("pointCut()")
    public void doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("===== Around before =====");
        pjp.proceed();
        System.out.println("===== Around after =====");
    }
}


// 一个接口
package cn.eagle.li.source.service;
public interface IService {
    void doService();
}

// 一个实现类
package cn.eagle.li.source.service.impl;
@Service
public class ServiceImpl implements IService {
    @Override
    public void doService() {
        System.out.println("do service");
    }
}


// Main类
@Configuration
@ComponentScan(basePackages = {"cn.eagle.li.source"})
@EnableAspectJAutoProxy(exposeProxy = true)
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
        IService service = context.getBean(IService.class);
        service.doService();
    }
}

执行结果如下:

===== Around before =====
===== Before =====
do service
===== AfterReturning =====
===== After =====
===== Around after =====

Spring AOP 原理

从@EnableAspectJAutoProxy注解入手

下面是EnableAspectJAutoProxy注解类内容

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
        //代理的实现方式,true为CGLIB, false为JDK,默认false
    boolean proxyTargetClass() default false;

     // 要不要暴露代理对象
    boolean exposeProxy() default false;
}

除了上面两个参数比较重要外,它还有一个Import注解,在Spring中,只要一种注解组合了另一种注解,它就具有该注解的功能,也就是这个注解拥有了@Import注解的功能。

@Import(AspectJAutoProxyRegistrar.class)

我们看到它import了AspectJAutoProxyRegistrar这个类,我们下面再看看这个类的内容,发现它主要的工作就是注册一个name为:

org.springframework.aop.config.internalAutoProxyCreator,类为AnnotationAwareAspectJAutoProxyCreator的BeanDefinition。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
             // ......
    }
}


AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);


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


public abstract class AopConfigUtils {

      public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
            "org.springframework.aop.config.internalAutoProxyCreator";

        @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;
        }

        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

                // 注册 BeanDefinition
                // AUTO_PROXY_CREATOR_BEAN_NAME = org.springframework.aop.config.internalAutoProxyCreator
                // beanDefinition = AnnotationAwareAspectJAutoProxyCreator.class
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }
}

此时有一个疑问:那就是什么时候调用这个方法来加载AnnotationAwareAspectJAutoProxyCreator这个类的BeanDefinition呢?

从下面这张图可以看到是在容器进行刷新的时候,调用invokeBeanFactoryPostProcessors这个方法来进行执行的,具体的执行过程就不展开了。

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                // Invoke factory processors registered as beans in the context.
                                // 在这里把beandefinition加载
                invokeBeanFactoryPostProcessors(beanFactory);
                                // ......
      }
    }

现在这个类的BeanDefinition准备好了,那什么时候会创建AnnotationAwareAspectJAutoProxyCreator这个实例,然后加载到容器里呢?

我们看一下这个类的继承关系,发现它是一个实现了BeanPostProcessor接口,也就是说它是一个后置处理器。在refresh()方法中有一个步骤是专门用来注册后置处理器的,也就是registerBeanPostProcessors()这个方法。

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                                // Register bean processors that intercept bean creation.
                                // 在这里把BeanPostProcessor加载到容器中
                registerBeanPostProcessors(beanFactory);
                                // ......
      }
    }

在调试的过程中,发现在PostProcessorRegistrationDelegate这个类下的registerBeanPostProcessors()这个方法下会创建AnnotationAwareAspectJAutoProxyCreator,并把它注册到容器中,如下图。

PostProcessorRegistrationDelegate类下
public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
}

经过上面的一个讨论,我总结了一下它的一些关键触发路径,如下:

refresh() -> invokeBeanFactoryPostProcessors() -> AspectJAutoProxyRegistrar.registerBeanDefinitions()

name:"org.springframework.aop.config.internalAutoProxyCreator" beanDefinition:AnnotationAwareAspectJAutoProxyCreator -> registerBeanPostProcessors() -> 创建类实例并加载到容器中

什么时候会创建代理对象?

容器里有了AnnotationAwareAspectJAutoProxyCreator这个实例,它具体有什么用呢,它什么时候会生成代理对象呢?

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

大家都知道,Spring在创建一个类实例后,会对这个类进行初始化,然后会执行一系列的后置处理器,就在applyBeanPostProcessorsAfterInitialization()这个方法里面。

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

它会依次地去调用每一个后置处理器,当然也包括了我们刚刚注册的AnnotationAwareAspectJAutoProxyCreator这个后置处理器,具体的执行方法就是postProcessAfterInitialization();

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

我们来看一下AnnotationAwareAspectJAutoProxyCreator类的postProcessAfterInitialization这个方法,发现如果没有包装过,就把它包装一下。

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


return wrapIfNecessary(bean, beanName, cacheKey);

我们看到它会获取一些适配这个类的Advices和Advisors,如果不为null,就创建一个代理对象。

    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);
                // DO_NOT_PROXY = 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;
    }


Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));


protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {
                // ......
        return proxyFactory.getProxy(targetClassLoader);
    }


    public Object getProxy(@Nullable ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }

Spring AOP有两种代理类,Jdk代理类和Cglib代理类,具体要看proxyTargetClass这个配置项和这个类是否实现了接口。

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

我们以JDK动态代理为例,发现它就是用Java的api进行创建的,代理类JdkDynamicAopProxy这个类

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    @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);
    }
}

到现在,我们知道,当创建一个bean实例后,在它初始化后,会调用每个后置处理器的初始化后的方法

当调用AOP的后置处理器的时候,会根据有没有适配它的advice和advitor来创建代理类

创建代理类的时候,有两种选择,一是JDK代理类,二是Cglib代理类

如果proxyTargetClass为false或者这个类没有实现接口的话,就选择Cglib代理类,否则选择JDK代理类。

方法执行时怎么实现拦截的?

现在我们获取一个bean时,获取的就是它的代理类,那在调用其方法时,哪些符合的通知是怎么一步步执行的呢?

我们以JDK代理类为例,我们都知道,在JDK动态代理中,实际执行的时候是执行的代理类的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;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                return AopProxyUtils.ultimateTargetClass(this.advised);
            }
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

                        // 如果设置了exposeProxy参数
                        // 这里暴露了代理对象
                        // AopContext.currentProxy() 获得
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // Get the interception chain for this method.
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                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);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}

总的看下来,主要关心以下内容:

// 如果设置了exposeProxy参数
// 这里暴露了代理对象
// AopContext.currentProxy() 获得
if (this.advised.exposeProxy) {
  // Make invocation available if necessary.
  // 这里是用ThreadLocal实现的
  oldProxy = AopContext.setCurrentProxy(proxy);
  setProxyContext = true;
}

// 创建拦截器链
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();
}

这个执行链就是一个数组,然后一个一个向下执行,根据之前的例子,这个生成的执行链如下:

AspectJAroundAdvice MethodBeforeAdviceInterceptor AspectJAfterAdvice AspectJAfterReturningAdvice

最终包装成ReflectiveMethodInvocation这个类,调用其proceed()方法执行,如下:

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

    public Object proceed() throws Throwable {
        // 拦截器链中的最后一个拦截器执行完
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                        // 执行目标方法
            return invokeJoinpoint();
        }

                // 每次执行新的拦截器,下标+1
        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);
        }
    }
}


public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
        ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
        JoinPointMatch jpm = getJoinPointMatch(pmi);
                // 调用通知的方法
        return invokeAdviceMethod(pjp, jpm, null, null);
    }
}


public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
    public Object invoke(MethodInvocation mi) throws Throwable {
                // 调用通知方法
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
                // 下一个拦截器
        return mi.proceed();
    }
}


public class AspectJAfterAdvice extends AbstractAspectJAdvice
        implements MethodInterceptor, AfterAdvice, Serializable {
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
                        // 下一个拦截器
            return mi.proceed();
        }
        finally {
                        // 调用通知方法
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }
}


public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
        implements MethodInterceptor, AfterAdvice, Serializable {
    public Object invoke(MethodInvocation mi) throws Throwable {
                // 下一个拦截器
        Object retVal = mi.proceed();
                // 调用通知方法
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }
}

===== Around before =====
===== Before =====
do service
===== AfterReturning =====
===== After =====
===== Around after =====

从上面可以看出,代理类执行的时候,就是将符合的advice排序得到一个数组,然后依次的进行执行。

总结

  1. 从EnableAspectJAutoProxy注解入手,Spring会注册AnnotationAwareAspectJAutoProxyCreator这个类
  2. AnnotationAwareAspectJAutoProxyCreator是个BeanPostProcessor,在初始化后,会调用后置处理器,生成代理对象
  3. 在类执行方法时,会生成一个数组,然后将所有相关的通知一个一个的执行

问题

我看看到上面的顺序是 AspectJAroundAdvice MethodBeforeAdviceInterceptor AspectJAfterAdvice AspectJAfterReturningAdvice

但是好多文章都说是AspectJAfterReturningAdvice AspectJAfterAdvice AspectJAroundAdvice MethodBeforeAdviceInterceptor

不同的执行顺序会对你的程序会有不同的影响

后续将会写一篇文章专门介绍这个原因

参考

Spring AOP

SpringAop源码分析(基于注解) 一

SpringAop源码分析(基于注解) 三

SpringAop源码分析(基于注解)四

Spring AOP执行顺序