美文网首页
Spring AOP源码

Spring AOP源码

作者: O_Neal | 来源:发表于2019-08-09 00:03 被阅读0次

    结合 Spring 后置处理器源码Spring Aware源码 ,再来看下 Spring AOP 的源码。

    启动 AOP

    使用 @EnableAspectJAutoProxy 这个注解来启用 AOP 的能力了。它使用 @Import 导入类 AspectJAutoProxyRegistrar,这个类实现了 ImportBeanDefinitionRegistrar,所以它会被 ConfigurationClassParser 扫描,并加入缓存中。然后 ConfigurationClassBeanDefinitionReader 从缓存中会拿到这个类,再执行其实现的方法 registerBeanDefinitions()。

    AspectJAutoProxyRegistrar.registerBeanDefinitions() 源码

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    }
    

    上述方法又使用 AOP 配置工具类 AopConfigUtils 将 AnnotationAwareAspectJAutoProxyCreator 也注册到 BeanFactory,其 name 为 org.springframework.aop.config.internalAutoProxyCreator。

    下图,展示了 AnnotationAwareAspectJAutoProxyCreator 的类继承关系

    AnnotationAwareAspectJAutoProxyCreator

    可以看出来 AnnotationAwareAspectJAutoProxyCreator 就是 BeanPostProcessor 和 Aware,其顶层抽象类 AbstractAutoProxyCreator 实现它们的接口。

    创建代理对象

    Spring Aware源码 中可知,BeanFactoryAware 实现类会在 invokeAwareMethods() 被回调 setBeanFactory() 方法,将 DefaultListableBeanFactory 注入给 AnnotationAwareAspectJAutoProxyCreator。

    InstantiationAwareBeanPostProcessor 新增了后置处理器方法 postProcessBeforeInstantiation() 和 postProcessAfterInstantiation(),这两个方法会在 Bean 初始化之前,也就是在 BeanPostProcessor 定义的方法之前先调用。

    • postProcessBeforeInstantiation() 会在反射调用 Bean 的构造器之前调用。
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 会返回一个代理对象,会执行 postProcessBeforeInstantiation()
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
        return doCreateBean(beanName, mbdToUse, args);
    }
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 从缓存获取
        Object cacheKey = getCacheKey(beanClass, beanName);
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // 判断是否已经在 advisedBeans 缓存
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            // 判断 Bean 是否是 Advice/Pointcut/Advisor/AopInfrastructureBean 这些不需要代理的基础类型;或者是否 @Aspect 注解类
            // 找到切面类中的所有通知方法,判断是否 AspectJPointcutAdvisor 类型,否则返回 false
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
        return null;
    }
    
    • postProcessAfterInstantiation() 会在给属性赋值的方法 populateBean() 中执行。
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {
        // 属性赋值,会执行 postProcessAfterInstantiation()
        populateBean(beanName, mbd, instanceWrapper);
        // 执行 BeanPostProcessor 的方法
        return initializeBean(beanName, exposedObject, mbd);
    }
    
    • BeanPostProcessor 的方法是在 initializeBean() 中才执行的。其中 postProcessAfterInitialization() 方法会获取切面类的所有通知方法,利用动态代理技术,创建增强的代理对象(比如:com.xxx.Service$$EnhancerBySpringCGLIB$$e86c6525@57eda880),同时会设置回调方法,完成后返回。
    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;
    }
    // 包装类
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 找到所有的候选通知方法
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 从候选通知方法找到可用于当前 Bean 的通知
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        // 获取所有的通知拦截器对象
        Object[] specificInterceptors = eligibleAdvisors.toArray();
        // 利用 AopProxy 来创建代理对象
        // AopProxy 包含 JDK 和 CGLib 两种实现
        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        return proxy;
    }
    

    至此,动态代理对象以及创建完成了,容器中就会有这个增强后的代理对象,方法执行时,也就会利用这个代理对象来执行通知方法了。

    执行代理对象

    执行被代理的方法时,会被 CglibAopProxy 拦截器拦截,获取这个方法的拦截器链。如果有拦截器链,则创建 CglibMethodInvocation 对象,执行 proceed(),即执行通知方法,最后返回 retVal,即方法的返回值;如果没有拦截器链,则直接执行方法;

    拦截器链实际上就是把方法拦截器放在 ArrayList 队列中,第一个默认是 ExposeInvocationInterceptor,剩下的默认顺序为 AspectJAfterThrowingAdvice、AspectJAfterReturningAdvice、AspectJAfterAdvice、AspectJAroundAdvice、AspectJMethodBeforeAdvice。

    proceed() 按照上面 ArrayList 中的顺序递归调用,当遇到 AspectJAroundAdvice、AspectJMethodBeforeAdvice 类型的通知时,会利用反射直接执行它们的通知方法,其他类型通知不会立即执行,会等待递归返回之后再行调用 invoke() 方法。这样,就能保证通知和方法的执行顺序:

    环绕通知执行 proceed() 前->前置通知->执行方法->环绕通知执行 proceed() 后->后置通知->返回通知->方法返回

    总结

    1. @EnableAspectJAutoProxy 使用 @Import(AspectJAutoProxyRegistrar.class) 导入 (AspectJAutoProxyRegistrar)ImportBeanDefinitionRegistrar。
    2. 容器刷新时,invokeBeanFactoryPostProcessors() 执行 (AspectJAutoProxyRegistrar)ImportBeanDefinitionRegistrar.registerBeanDefinitions() 注册 AnnotationAwareAspectJAutoProxyCreator 到 BeanFactory。
    3. AnnotationAwareAspectJAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor 和 BeanFactoryAware,在 registerBeanPostProcessors() 将其注册到 BeanFactory,并且执行 invokeAwareMethods() 回调 (AbstractAdvisorAutoProxyCreator)BeanFactoryAware.setBeanFactory() 方法。
    4. finishBeanFactoryInitialization() 执行 (AnnotationAwareAspectJAutoProxyCreator)BeanPostProcessor.postProcessAfterInitialization(),找到切面类及其切面通知方法,使用动态代理技术(ObjenesisCglibAopProxy/JdkDynamicAopProxy),对切面类进行增强,创建增强后的代理对象com.xxx.Service$$EnhancerBySpringCGLIB$$e86c6525@57eda880
    5. 执行被代理的方法时,会被 CglibAopProxy 的拦截器拦截,拿到方法的拦截器链,按顺序递归调用,利用反射技术执行通知方法,以此实现不同通知的调用顺序。

    相关文章

      网友评论

          本文标题:Spring AOP源码

          本文链接:https://www.haomeiwen.com/subject/oreqjctx.html