Skip to content

AOP 源码解读

其他博客参考:https://blog.csdn.net/l6108003/article/details/106577515/

SPI 读取 AopAutoConfiguration 配置类

在 spring-boot-autoconfigure-2.5.3.jar 中通过 SPI 读取自动配置类 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;

使用时是否需要添加 @EnableAspectJAutoProxy ?

从配置类中可以看出,SpringBoot 默认已经开启了 AOP,故使用时,无需再添加 @EnableAspectJAutoProxy 注解。

java
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
		static class JdkDynamicAutoProxyConfiguration {

		}

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {

		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
			matchIfMissing = true)
	static class ClassProxyingConfiguration {

		@Bean
		static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
			return (beanFactory) -> {
				if (beanFactory instanceof BeanDefinitionRegistry) {
					BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
				}
			};
		}

	}
}

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy 导入了 @Import(AspectJAutoProxyRegistrar.class) 类。 Spring 在处理 @Import 注解时,就会实例化导入的这个类和执行到这个类的顶层父类 ImportBeanDefinitionRegistrar.registerBeanDefinitions() 方法。

java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 * true: 无论目标对象有没有实现接口,都是用 CGLIB 动态代理。
	 * false: 目标对象实现了接口,使用 JDK 动态代理;目标对象没有实现接口,则使用 CGLIB 动态代理。
	 * 注:JDK 动态代理必须目标对象实现接口。CGLIB 则没有这个要求。
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
     * 该属性设置代理对象是否需要暴露,说白了就是是否需要把代理对象设置到 ThreadLocal 中。
     * 要获取代理对象,就可以使用 AopContext.currentProxy()。
	 */
	boolean exposeProxy() default false;
}

AspectJAutoProxyRegistrar

这里主要是将 AnnotationAwareAspectJAutoProxyCreator 注册到 spring 中。

java
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 这里将 AnnotationAwareAspectJAutoProxyCreator 注册到 spring 中
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}

AnnotationAwareAspectJAutoProxyCreator

AspectJAutoProxyRegistrar 类的继承关系如下:

├─AnnotationAwareAspectJAutoProxyCreator
│ ├─ extends AbstractAdvisorAutoProxyCreator
│   ├─ extends AbstractAutoProxyCreator
│     ├─extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
│       ├─SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
│         └─extends BeanPostProcessor

可以看出,它其实主要是一个 BeanPostProcessor 后置处理器类。 BeanPostProcessor 是在普通 Bean 之前实例化的,这就意味着,普通 Bean 在初始化的过程中会被各种 BeanPostProcessor 进行拦截。 最终在实例化 bean 之后,调用后置处理器的时候执行到 BeanPostProcessor.postProcessAfterInitialization() 方法,返回 AOP 代理对象。

AopConfigUtils

java
public abstract class AopConfigUtils {

    /**
     * The bean name of the internally managed auto-proxy creator.
     */
    public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
            "org.springframework.aop.config.internalAutoProxyCreator";

    /**
     * Stores the auto proxy creator classes in escalation order.
     */
    private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

    static {
        // Set up the escalation list...
        // InfrastructureAdvisorAutoProxyCreator 用于处理以 @EnableTransactionManagement 注解形式开启事务。因为事务底层也是AOP实现的。
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        // AspectJAwareAdvisorAutoProxyCreator用于处理以 <aop:aspectj-autoproxy proxy-target-class="true"/> xml 配置形式开启AOP。
        APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
        // AnnotationAwareAspectJAutoProxyCreator 用于处理以 @AspectJ 注解形式开启AOP。
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }
    // 省略其他代码
}

入口?在哪里调用的 AnnotationAwareAspectJAutoProxyCreator?

├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object beanInstance = doCreateBean(beanName, mbdToUse, args);
│ │ │ │ │ │ │ │ ├─instanceWrapper = createBeanInstance(beanName, mbd, args);
│ │ │ │ │ │ │ │ ├─下面是依赖注入的核心方法(非常重要)
│ │ │ │ │ │ │ │ ├─populateBean(beanName, mbd, instanceWrapper);
│ │ │ │ │ │ │ │ ├─下面是依赖注入完成后的调用(非常重要)
│ │ │ │ │ │ │ │ ├─exposedObject = initializeBean(beanName, exposedObject, mbd);
│ │ │ │ │ │ │ │ │ ├─AOP 的入口方法。这里完成对 AnnotationAwareAspectJAutoProxyCreator(实际是一个 BeanPostProcessor) 的使用。
│ │ │ │ │ │ │ │ │ ├─wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

由于 AnnotationAwareAspectJAutoProxyCreator 继承了 AbstractAutoProxyCreator 类,进而又实现了 BeanPostProcessor 接口, 那么这里就会执行到 BeanPostProcessor.postProcessAfterInitialization() 方法,返回 AOP 代理对象。

由于 AbstractAutoProxyCreator 类重写了 postProcessAfterInitialization() 方法,因此,最终会调到这里。

java
// 类中省略了其他方法的代码
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 这里创建了代理对象,并返回。最终这个对象会在 Spring 容器中
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    /**
     * 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.
        // 如果这个bean有advice的话,则创建当前bean的代理,重点看,重要程度5
        // 得到所有的可用于拦截当前 bean 的 advisor、advice、interceptor
        // 筛选查找有 advice 的 bean,并包装为 List<Advisor> 返回。
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //如果有切面,则生成该bean的代理,并把被代理对象bean实例封装到 SingletonTargetSource 对象中
            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;
    }


    /**
     * 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();
        // 把 AnnotationAwareAspectJAutoProxyCreator 中的某些属性copy到proxyFactory中
        proxyFactory.copyFrom(this);

        if (proxyFactory.isProxyTargetClass()) {
            // Explicit handling of JDK proxy targets (for introduction advice scenarios)
            if (Proxy.isProxyClass(beanClass)) {
                // Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
                for (Class<?> ifc : beanClass.getInterfaces()) {
                    proxyFactory.addInterface(ifc);
                }
            }
        }
        else {
            // No proxyTargetClass flag enforced, let's apply our default checks...
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        // 组装advisor
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        // 把advisor加入到proxyFactory
        proxyFactory.addAdvisors(advisors);
        // 把targetSource对象加入到proxyFactory
        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);
    }
}

getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

找到合法的 Advice 类。

java
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    /**
     * 查找 @Aspect 注解的类,核心方法
     */
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 找到候选的切面,其实就是一个寻找有 @Aspect 注解的过程,把工程中所有有这个注解的类封装成Advisor返回
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 判断候选的切面是否作用在当前beanClass上面,就是一个匹配过程。
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            //对有@Order@Priority进行排序
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

}

如何查找当前 bean 的切面

  • 从 Spring 中查找所有的切面
    • 首先找到所有的 BeanDefinition 对象对应的 beanName,反射拿到对应的 Class 对象,判断该类上面是否有 @Aspect 注解,有则是我们要找的;
    • 然后循环该 Class 里面的除了@PointCut 注解的方法,找到方法上的 Around.class,Before.class, After.class,AfterReturning.class,AfterThrowing.class 注解,并且把注解里面的信息,比如表达式、argNames、注解类型等信息封装成对象 AspectJAnnotation;
    • 接着创建 pointCut 对象,把注解对象中的表达式设置到 pointCut 对象中;
    • 最后就是创建 Advice 对象,根据不同的注解类型创建出不同的 Advice 对象,对象如下 :AspectJAroundAdvice,AspectJAfterAdvice, AspectJAfterThrowingAdvice,AspectJMethodBeforeAdvice, AspectJAfterReturningAdvice 最终把注解对应的 Advice 对象和 pointCut 对象封装成 Advisor 对象。
  • 找到拦截当前 bean 的切面
    • 从收集到的所有切面中,每一个切面都会有 pointCut 来进行模块匹配,其实这个过程就是一个匹配过程,看看 pointCut 表达式中的内容是否包含了当前 bean,如果包含了,那么这个 bean 就有切面,就会生成代理。 :::

小结

代理对象的创建过程整体来说并不复杂,首先找到所有带有@Aspect 注解的类,并获取其中没有@Pointcut 注解的方法,循环创建切面, 而创建切面需要切点和增强两个元素,其中切点可简单理解为我们写的表达式,增强则是根据@Before、@Around、@After 等注解创建的对应的 Advice 类。 切面创建好后则需要循环判断哪些切面能对当前的 Bean 实例的方法进行增强并排序,最后通过 ProxyFactory 创建代理对象。