美文网首页IT小白
spring aop 原理笔记

spring aop 原理笔记

作者: 边学边记 | 来源:发表于2019-03-20 16:48 被阅读0次

    AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

    实现AOP的技术,主要分为两大类:
    一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
    二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

    AOP使用场景
    AOP用来封装横切关注点,具体可以在下面的场景中使用:

    Authentication 权限
    Caching 缓存
    Context passing 内容传递
    Error handling 错误处理
    Lazy loading 懒加载
    Debugging  调试
    logging, tracing, profiling and monitoring 记录跟踪 优化 校准
    Performance optimization 性能优化
    Persistence  持久化
    Resource pooling 资源池
    Synchronization 同步
    Transactions 事务

    代理方式:
    cjlib CGLIB底层封装了ASM,通过对字节码的操作来生成类,具有更高的性能。
    jdkproxy 代理 接口方式 InvocationHandler,Proxy,

    aop 源码解读笔记
    第一阶段:AnnotationAwareAspectJAutoProxyCreator组件(ASPECT自动代理创建器),注册组件
    @EnableAspectJAutoProxy//开启aop- spring开启aop注解
    public @interface EnableAspectJAutoProxy
    boolean proxyTargetClass() default false; --默认false,采用JDK动态代理织入增强(实现接口的方式);如果设为true,则采用CGLIB动态代理织入增强
    boolean exposeProxy() default false;--是否可以根据aopContext进行检索
    @Import(AspectJAutoProxyRegistrar.class)----导入(注册这个bean)
    进入 AspectJAutoProxyRegistrar -》
    AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
    它实现了 ImportBeanDefinitionRegistrar(动态导入bean)
    要实现的方法
    public void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
    作用:根据值注册,升级和配置AspectJ自动代理创建程序 会根据前面注解中配置的代理方式来注册这个组件

    @Override
    public void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    //注册一个这个组件, 如果有需要的话....
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    AnnotationAttributes enableAspectJAutoProxy =
    AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    //代理方式?
    if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }
    //这里根据之前注解进来的参数 要不要放到ExposeProxy?
    if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
    }

    继续跟进:AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    -》
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
    }
    -》
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

    分析:registerOrEscalateApcAsRequired 注册或者升级---AnnotationAwareAspectJAutoProxyCreator.class
    (这就是第一阶段我们要注册的aop组件)

    tip: 这里
    BeanDefinitionRegistry 是一个接口, 实现了AliasRegistry接口, 定义了一些对 bean的常用操作
    1: 以Map<String, BeanDefinition>的形式注册bean
    2:根据beanName 删除和获取 beanDefiniation ,得到持有的beanDefiniation的数目,根据beanName 判断是否包含 beanDefiniation等

    接上面 registerOrEscalateApcAsRequired 流程
    通过registry判断org.springframework.aop.config.internalAutoProxyCreator 在容器中有没有
    第一次没有存在 则 去创建 (org.springframework.aop.config.internalAutoProxyCreator 内部定义的组件名)
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", -2147483648);
    beanDefinition.setRole(2);
    registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
    return beanDefinition;

    AnnotationAwareAspectJAutoProxyCreator神奇的组件分析:
    类关系图如下,继承关系:
    AnnotationAwareAspectJAutoProxyCreator:

    • AnnotationAwareAspectJAutoProxyCreator
    • ->AspectJAwareAdvisorAutoProxyCreator
    •    ->AbstractAdvisorAutoProxyCreator
      
    •       ->AbstractAutoProxyCreator
      
    •         implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
      
    •                  关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactory
      

    SmartInstantiationAwareBeanPostProcessor: bean的后置处理器
    BeanFactoryAware 能把beanFacotry bean工厂传进来
    通过分析以上的bean继承关系我们发现, 具有BeanPostProcessor特点, 也有Aware接口的特点, 实现了BeanFactoryAware 接口

    其实是一个spring组件,会有后置处理器在工作 并且拿到了beanFacotry bean

    那我们来分析做为beanPostProcessor后置处理器做了哪些工作, 做为BeanFactoryAware又做了哪些工作

    第二阶段:AnnotationAwareAspectJAutoProxyCreator 的工作原理
    实现了beanPostProcessor 所以容器会怼他创建成一个后置处理器类 放入容器
    定制了一个 特置的后置处理器
    其他bean在创建时 将(增强器 切面类)放入advisedBeans (map)中
    给增强器排序
    需要增强的bean创建代理类过程
    1)、获取当前bean的所有增强器(通知方法) Object[] specificInterceptors
    1、找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
    2、获取到能在bean使用的增强器。
    3、给增强器排序
    2)、保存当前bean在advisedBeans中;
    3)、如果当前bean需要增强,创建当前bean的代理对象;
    1)、获取所有增强器(通知方法)
    2)、保存到proxyFactory
    3)、创建代理对象:Spring自动决定
    JdkDynamicAopProxy(config);jdk动态代理;
    ObjenesisCglibAopProxy(config);cglib的动态代理;
    4)、给容器中返回当前组件使用cglib增强了的代理对象;
    5)、以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;

    保存需要代理对象和增强器

    第三阶段:目标执行
    容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);
    1)、CglibAopProxy.intercept();拦截目标方法的执行
    2)、根据ProxyFactory对象获取将要执行的目标方法拦截器链;
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    1)、List<Object> interceptorList保存所有拦截器 5
    一个默认的ExposeInvocationInterceptor 和 4个增强器;
    2)、遍历所有的增强器,将其转为Interceptor;
    registry.getInterceptors(advisor);
    3)、将增强器转为List<MethodInterceptor>;
    如果是MethodInterceptor,直接加入到集合中
    如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
    转换完成返回MethodInterceptor数组;

       3)、如果没有拦截器链,直接执行目标方法;
           拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
       4)、如果有拦截器链,把需要执行的目标对象,目标方法,
           拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
           并调用 Object retVal =  mi.proceed();
       5)、拦截器链的触发过程;
           1)、如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
           2)、链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
              拦截器链的机制,保证通知方法与目标方法的执行顺序;

    相关文章

      网友评论

        本文标题:spring aop 原理笔记

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