上一篇介绍了实现AOP的两种方式,本篇我们通过分析源码流程,来看一下注解版AOP的实现。具体的源码细节,会在后面的篇章一行行翻译。

1.开启AOP的功能

读源码需要找到入口或者抓手,AOP的源码我们如何入手呢?想要使用AOP的功能就需要在Spring的配置类上加上**@EnableAspectJAutoProxy**注解。

先分析一下这个注解:

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(AspectJAutoProxyRegistrar.class)
  5. public @interface EnableAspectJAutoProxy {
  6. /**
  7. * 是否要创建基于子类 (CGLIB) 的代理,而不是基于标准 Java 接口的代理。 默认值为false 。
  8. * @return
  9. */
  10. boolean proxyTargetClass() default false;
  11. /**
  12. * 代理应由 AOP 框架公开为ThreadLocal以通过AopContext类进行检索。
  13. * 默认关闭,即不保证AopContext访问将起作用。
  14. */
  15. boolean exposeProxy() default false;
  16. }

可以看到这个注解的底层有一个**@Import(AspectJAutoProxyRegistrar.class)**,他往容器中导入了一个组件**AspectJAutoProxyRegistrar**

看一下这个组件:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {


    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        /*导入组件到容器中 AnnotationAwareAspectJAutoProxyCreator*/
        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);
            }
        }
    }

}
    @Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {
        /*
        * 参数一:固定类型
        * 参数二:spring容器
        * 参数三:标签
        * */
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }


**AspectJAutoProxyRegistrar** 实现了 **ImportBeanDefinitionRegistrar**接口,往容器中注册了一个bd信息。**AnnotationAwareAspectJAutoProxyCreator**

2.加载时机


上一节我们分析到,在Spring的配置类上打一个注解,最后总会往容器中导入一个类:**AnnotationAwareAspectJAutoProxyCreator**

我们来分析一下这个类的继承关系:
image.png

image.png

按照顺序分析一下这个类的加载时机和加载的时候,里面的 **initBeanFactory()** & **setBeanFactory()** 是什么时候执行的。

image.png


  1. 首先执行的是**AbstractAdvisorAutoProxyCreator****setBeanFactory()**
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException(
                    "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    }
  1. 接下来执行的是**AbstractAutoProxyCreator****setBeanFactory()**

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
  1. 然后执行的是**AnnotationAwareAspectJAutoProxyCreator****initBeanFactory()**
    @Override
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.initBeanFactory(beanFactory);
        if (this.aspectJAdvisorFactory == null) {
            this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
        }
        this.aspectJAdvisorsBuilder =
                new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    }
  1. 最终执行的是**AbstractAdvisorAutoProxyCreator****initBeanFactory()**
    protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
    }

接下来分析**AnnotationAwareAspectJAutoProxyCreator**的执行时机。

3.创建代理对象

AOP的加载时机.jpg

4.获取拦截器

image.png

5.链式调用通知方法

image.png

6.流程总结

image.png

AOP其实就是往容器中导入了一个组件,这个组件是一个后置处理器,他会在对象创建之前尝试返回一个代理对象,如果不能成功返回,会在对象创建之后,init方法执行前后去判断当前对象是否需要被代理,如果需要被代理则根据各种条件去选择代理方式,创建代理对象,同时会去判断哪些切面和方法需要增强代理对象里面的方法,生成一条拦截器链。 � �在代理对象执行目标方法前后,通过拦截器对目标方法进行拦截,执行增强逻辑。