SpringFramework — AOP代理的底层核心后置处理器

小龙 451 2022-06-08

开启 AOP 的核心说起,那要从 @EnableAspectJAutoProxy 注解开始

@EnableAspectJAutoProxy的作用

翻开 @EnableAspectJAutoProxy 注解的源码,可以发现它 @Import 了一个注册器:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass() default false;
	boolean exposeProxy() default false;
}

AspectJAutoProxyRegistrar 与后置处理器

看一眼它的文档注释,会发现它已经把核心的后置处理器给说出来了:

Registers an AnnotationAwareAspectJAutoProxyCreator against the current BeanDefinitionRegistry as appropriate based on a given @EnableAspectJAutoProxy annotation.

根据给定的 @EnableAspectJAutoProxy 注解,根据当前 BeanDefinitionRegistry 在适当的位置注册 AnnotationAwareAspectJAutoProxyCreator 。

由此可知,AOP 的核心后置处理器是 AnnotationAwareAspectJAutoProxyCreator

先了解一下 AspectJAutoProxyRegistrar 是在什么时机下注册 AnnotationAwareAspectJAutoProxyCreator 的。

AspectJAutoProxyRegistrar注册后置处理器的时机

由于 AspectJAutoProxyRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,所以我们可以直接找到 registerBeanDefinitions 方法,去寻找注册的逻辑。

public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    // 核心注册后置处理器的动作
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    // 解析@EnableAspectJAutoProxy的属性并配置
    AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

在第一句就明示了它要注册后置处理器,也就是代理的创建器了。而这个方法也指明了它要注册的 bean 的类型就是 AnnotationAwareAspectJAutoProxyCreator :

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    // 此处已指定类型
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

再往下,就是根据这个类型,构造 BeanDefinition ,并注册进 BeanDefinitionRegistry 的动作了,逻辑相对简单,小伙伴们扫一眼就可以了:

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

    // 构造BeanDefinition,注册进BeanDefinitionRegistry
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

AnnotationAwareAspectJAutoProxyCreator 代理对象的创建器

javadoc 中的描述

AspectJAwareAdvisorAutoProxyCreator subclass that processes all AspectJ annotation aspects in the current application context, as well as Spring Advisors. Any AspectJ annotated classes will automatically be recognized, and their advice applied if Spring AOP’s proxy-based model is capable of applying it. This covers method execution joinpoints. If the aop:include element is used, only @AspectJ beans with names matched by an include pattern will be considered as defining aspects to use for Spring auto-proxying. Processing of Spring Advisors follows the rules established in org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.

它是 AspectJAwareAdvisorAutoProxyCreator 的子类,用于处理当前 ApplicationContext 中的所有基于 AspectJ 注解的切面,以及 Spring 原生的 Advisor 。

如果 Spring AOP 基于代理的模型能够应用任何被 @AspectJ 注解标注的类,那么它们的增强方法将被自动识别。这涵盖了方法执行的切入点表达式。

如果使用 aop:include 元素,则只有名称与包含模式匹配的被 @AspectJ 标注的 bean 将被视为定义要用于 Spring 自动代理的方面。

Spring 中内置的 Advisor 的处理遵循 AbstractAdvisorAutoProxyCreator 中建立的规则。

javadoc 中解释的核心内容是,AnnotationAwareAspectJAutoProxyCreator 它兼顾 AspectJ 风格的切面声明,以及 SpringFramework 原生的 AOP 编程。

AnnotationAwareAspectJAutoProxyCreator的继承结构

image-1654674723193

  • BeanPostProcessor :用于在 postProcessAfterInitialization 方法中生成代理对象
  • InstantiationAwareBeanPostProcessor :拦截 bean 的正常 doCreateBean 创建流程
  • SmartInstantiationAwareBeanPostProcessor :提前预测 bean 的类型、暴露 bean 的引用( AOP 、循环依赖等)
  • AopInfrastructureBean :实现了该接口的 bean 永远不会被代理(防止套娃)

nnotationAwareAspectJAutoProxyCreator 的初始化时机

前面在 AspectJAutoProxyRegistry 中已经把 AnnotationAwareApsectJAutoProxyCreatorBeanDefinition 注册到 BeanDefinitionRegistry 中了。在 refresh() 中初始化后置处理器部分,该后置处理器一定会被创建。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // ......
        try {
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            // 6. 注册、初始化BeanPostProcessor
            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            // ......
    }
}

AnnotationAwareAspectJAutoProxyCreator 实现了 Ordered 接口,它会提前于普通 BeanPostProcessor 创建,代表着普通的 BeanPostProcessor 也会被 AOP 代理。

AnnotationAwareAspectJAutoProxyCreator 的作用时机

getBean 开始,依次是 doGetBeancreateBeandoCreateBean ,在 doCreateBean 方法中会真正的创建对象属性赋值依赖注入,以及初始化流程的执行。等 bean 本身的初始化流程全部执行完毕后,就该 BeanPostProcessorpostProcessAfterIntialization 方法

createBeandoCreateBean 这个动作中还有一个 InstantiationAwareBeanPostProcessor 的拦截初始化动作

AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation(AbstractAutoProxyCreator)

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);
    // 决定是否要提前增强当前bean
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // 被增强过的bean不会再次被增强
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 基础类型的bean不会被提前增强、被跳过的bean不会被提前增强
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }
    // 原型bean的额外处理:TargetSource
    // 此处的设计与自定义TargetSource相关,单实例bean必定返回null
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    return null;
}

InfrastructureClass

判断 bean 是否为基础类

protected boolean isInfrastructureClass(Class<?> beanClass) {
    return (super.isInfrastructureClass(beanClass) ||
            (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
protected boolean isInfrastructureClass(Class<?> beanClass) {
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
            Pointcut.class.isAssignableFrom(beanClass) ||
            Advisor.class.isAssignableFrom(beanClass) ||
            AopInfrastructureBean.class.isAssignableFrom(beanClass);
    // logger ......
    return retVal;
}

基础类包含了这些基础类型,是切面、切入点、增强器等等的对象

被跳过的bean

// AspectJAwareAdvisorAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 加载增强器
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        // 逐个匹配,如果发现当前bean的名称与增强器的名称一致,则认为
        if (advisor instanceof AspectJPointcutAdvisor &&
                ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    return super.shouldSkip(beanClass, beanName);
}

// AbstractAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 检查beanName代表的是不是原始对象(以.ORIGINAL结尾)
    return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

检查当前对象的名称是不是有跟增强器的名称撞车的,或者说它是不是一个还没有经过任何代理的原始对象。对于一般情况而言,我们构造的 bean 根本就不可能带有 .ORIGINAL 的后缀,所以这个地方相当于判断当前创建的 bean 是否名称与增强器撞车。

这里咱简单说下增强器的概念。一个 Advisor 可以视为一个切入点 + 一个通知方法的结合体,对于 Aspect 切面类中定义的通知方法,方法体 + 方法上的通知注解就可以看做一个 Advisor 增强器

TargetSource

AOP 的代理其实不是代理的目标对象本身,而是目标对象包装后的 TargetSource 对象。

AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization(AbstractAutoProxyCreator)

前面的拦截判断结束后,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;
}

最关键的动作是中间的 wrapIfNecessary 方法。这个动作从方法名上就可以很容易的理解了,如果有必要的话,给这个对象包装生成代理对象。

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

创建代理对象的核心动作分为三个步骤:

  1. 判断决定是否是不会被增强的 bean
  2. 根据当前正在创建的 bean 全区匹配增强器

# AOP