zoukankan      html  css  js  c++  java
  • spring源码分析——Aop的流程

      上面章节我们花费了大量的时间分析IOC,控制反转,反转控制对象的创建以及维护对象之间的依赖关系,对象的销毁

    1:对象的创建,加载并解析xml文件或者注解,生成BeanDefinition对象,实例化BeanDefinitionRegistryPostProcessor并调用重写方法,实例化并注册BeanPostProcessor 

    的后置接口,预实例化非懒加载的单例对象。

    2:维护对象的依赖关系, set注入、构造器注入、@Autowired 的依赖注入等

    3:对象的销毁,注册可销毁的回调接口,以及销毁接口的调用

    一:Aop的使用

    下面我们来重点分析一下Aop的实现原理,首先我们来看一下面向切面编程的使用,

    测试代码:

     从运行结果看方法被拦截,说明代理成功:

    二:源码层面分析Aop

    1:看一下开启Aop的配置具体做了什么,这是一个自定义标签aop,是通过命名空间加载的handler处理类

    spring.handlers处理类

    public class AopNamespaceHandler extends NamespaceHandlerSupport {
    
    	/**
    	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
    	 * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
    	 * and '{@code scoped-proxy}' tags.
    	 * AopNamespaceHandler 命名空间handler实例化完成后,会调用init进行初始化,
    	 * 在初始化中完成各种元素解析器的注册
    	 */
    	@Override
    	public void init() {
    		// In 2.0 XSD as well as in 2.1 XSD.
    		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
    
    		// Only in 2.0 XSD: moved to context namespace as of 2.1
    		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    	}
    
    }
    

        

    处理器init方法中,有一个AspectJAutoProxyBeanDefinitionParser的解析器:

     

     AnnotationAwareAspectJAutoProxyCreator 这个类将会被注册到BeanDefinitionMaps中

     

     到这里动态代理的BeanPostProcessor以BeanDefinition的形式注册到BeanDefinitionMaps中就完成了。

    2:在refresh方法中,registryBeanPostProcessor方法中,会实例化所有的BeanPostProcessor对象,并注册到beanPostProcessors中,以备后续使用。

    3:使用BeanPostProcessor创建代理对象

    创建代理对象是在initializeBean方法中beanPostProcessor的after接口中进行的

     调用代理PostProcessor的后置接口方法:

    这wrapIfNecessary中进行代理:

    获取切面通知,并创建代理,然后返回,大致的流程是这样,我们再来看一下细节部分:

    获取切面通知:

     

     寻找所有切面类:

    寻找切面类的所有增强:

    搜集切面类的所有非切点方法:

     每个Advisor维护了Advice对象

    getAdvice方法:

     根据注解类型 判断 是创建Before 、After、Around 的通知器Advice

    到这里就把所有的@Aspect类里所有的非切点方法,搜集到了,封装成Advisor对象,每个Advisor对象维护了一个Advice对象。

    看一下和当前bean的匹配

    匹配当前类:

     

     将匹配的Advisor返回,到这里所有匹配的bean的增强通知器Advisor都被搜集到了。

    下一步就是创建代理:

     

     

    到这里代理对象创建完成。

     对象已经被代理

    所以注册到一级缓存中的对象也是代理对象

    4:调用某个接口实际上就是调用代理的invoke

     

    先调用after的Advice

    再调用around的Advice

    进入around的切面方法:

     调到before的Advicefang方法:

     调用before的切面方法:

    然后调到真正的test方法

    最后调到after的通知方法,在finally代码块中:

     

    到这里调用链的调用就结束了。

    总结:aop的流程主要有一下步骤:

    1:注册BeanDefinition,在xml中配置aop自定义标签或者注解开启Enable都会注册动态代理的BeanPostProcessor接口

    2:在registryBeanPostProcessor中实例化对象并注册到beanPostProcessors集合中,以备后面使用

    3:在预实例化第一个bean的时候就会搜集所有的Aspect切面信息,然后获取切面信息的Advisor,缓存起来

    4:拿所有的bean匹配Advisor信息,如果能够匹配上,把Advisor的对象放入放入中返回,如果不为空,则创建该bean的代理对象。

    5:当调用该bean的方法时,会调用到横切面上,然后调用链会依次调用链中的放入,对方法进行增强。

  • 相关阅读:
    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程
    002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介
    001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学
    001 Android Studio 首次编译执行项目过程中遇到的几个常见问题
    Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器
    Dora.Interception,为.NET Core度身打造的AOP框架 [1]:更加简练的编程体验
    监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
    轻量级ORM框架——第二篇:Dapper中的一些复杂操作和inner join应该注意的坑
    轻量级ORM框架——第一篇:Dapper快速学习
    CF888G Xor-MST(异或生成树模板)
  • 原文地址:https://www.cnblogs.com/warrior4236/p/13254112.html
Copyright © 2011-2022 走看看