zoukankan      html  css  js  c++  java
  • Spring--AOP的见解

    AOP是指面向切面编程,与JAVA中的动态代理有很深的渊源。

    在使用Spring框架时,AOP编程能简化很多繁杂的步骤,精简代码。

    切面:横切关注点(跨越程序中多个模块的功能),被模块化的特殊对象,也可以认为是抽取了一些通用的东西当成一个“面”;

    通知:切面必须要完成的工作(切面中的每一个方法被称之为通知),可以认为抽取出来的切面(类)中的方法都是一个通知;

    目标:被通知的对象(业务逻辑),也就是被包裹的方法。或者说要实现的目标方法;

    代理:向目标对象应用通知之后创建的对象;

    连接点:程序执行的某个特定位置(比如调用某一方法之前,调用某一方法之后);

        由以下两个基本信息来决定:

    1. 方法:这个方法就是表示程序的执行点(程序执行到了此处);
    2. 相对点:相对点执行的方位(即当前执行方法之前?之后?异常时?)     

    切点:每个类都会有很多个连接点(因为一个类可以有多个方法,所以会存在很多个切入点);

            AOP通过切点定位到特定的连接点

            连接点相当于数据库中的一条数据,是真实存在的。而切入点则是查询这个数据的方法。也就是说一个切点(条件)可以多个连接点(查到很多的记录)

    AOP的原理(注解版):

    1.  @EnableAspectJAutoProxy:开启AOP功能;
    2.  @EnableAspectJAutoProxy:这个注解会给容器注册一个组件AnnotationAwareAspectJAutoProxyCreator;
    3.  AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;
    4.  容器创建流程:
      1. registerBeanPostProcessors()注册后置处理器创建对象AnnotationAwareAspectJAutoProxyCreator;
      2. finishBeanFactoryInitialization()初始化剩下的单实例Bean:
        1. 床架业务逻辑组件和切面组件;
        2. AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程;
        3. 组件创建完成之后判断组件是否需要被包装(增强);如果需要就将切面的通知方法包装成增强器(advisor);给业务逻辑组件创建一个代理对象;
    5.  目标方法执行:
      1. 代理对象执行目标方法;
      2. cglibAopProxy.intercept();
        1. 得到目标方法的拦截器(增强器包装成MethodInterceptor);
        2. 利用拦截器的链式机制,依次进入每个拦截器执行;

    2. @EnableAspectJAutoProxy:这个注解会给容器注册一个组件AnnotationAwareAspectJAutoProxyCreator:

    1. 首先是由配置类创建IOC容器
    2. 注册配置类,调用refresh()刷新容器
    3. registerBeanPostProcessors(beanFactory);注册Bean的后置处理器(这个关系到AOP的后置拦截器,他专拦截Bean创建)来方便拦截Bean创建:
      1. 首先获取IOC容器一定定义好的需要创建对象的所有后置处理器;
      2. 给容器中加入别的Bean的后置处理器;
      3. 有限注册实现了PriorityOrdered接口的Bean的后置处理器,再来是实现了Ordered接口Bean的后置处理器;最后是注册那些没有实现(标注)优先级接口的Bean的后置处理器;
      4. 注册其实就是创建后置处理器并且保存在IOC容器中,因为这是在创建IOC容器;
        1. 创建Bean实例;
        2. populateBean:给Bean的各种属性赋值;
        3. initializeBean:初始化Bean的方法
          1. invokeAwareMethods():处理Aware接口的方法回调;
          2. applyBeanPostProcessorsBforeInitlization:前置方法调用;
          3. invokeinitMethids()初始化方法;
          4. 调用后置方法applyBeanPostProcessorsAfterInitlization;
    4. BeanPostProcessor创建成功,开始搞那些Bean实例化什么的常规操作;

    3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器:他会试图拦截每一个Bean的创建,并且返回一个对象    ||    容器创建流程

    1. 在每一个Bean创建之前都调用PostProcessBeforeInstantiation()方法;
    2. 判断当前Bean是否在adviseBeans中;
    3. 判断当前Bean是不是基础类型(Advice,Pointcut,Advisor,AopIntrastructureBean),或者是切面@Aspect;
    4. 判断是否需要跳过
      1. 判断候选增强器(就是指这个切面中的方法),每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor类型;
      2. 判断每一个增强器是否是AspectJPointcutAdvisor类型返回True;
      3. 其他的永远返回false;
    5. 创建好对象之后,后置方法postProcessAfterInitialization:return warpIfNecessary(bean,beanName,cachekey),在需要的时候包装(判断时候需要被切面环绕咯~)
      1. 获取所有的增强器(通知方法),封装未一个Object[ ]数组;
        1. 找到增强器(找到需要切入到当前程序运行时切入当前Bean的通知方法);
        2. 获取到当前Bean使用的增强器;
        3. 给增强器排个序;
      2. 保存Bean在adviseBean中;
      3. 如果当前Bean需要增强,创建Bean的代理对象
        1. 获取所有的增强器;
        2. 保存到proxyFactory中;
        3. 创建代理对象(这个有Spring来决定)
          1. JDK动态代理对象,JDKDynamicAopProxy(config);
          2. cglib动态代理对象,ObjenesisCglibAopProxy(config);
      4. 给容器中返回当前组件使用的cglib增强之后的代理对象;
      5. 之后在执行目标方法的时候,调用的就是这个已经被注入的代理对象;

    4.目标方法执行

    1.  容器中此时已经存在的是组件的cglib代理对象
      1. cglibAopProxy,interceot();拦截目标方法执行;
      2. 根据ProxyFactory对象获取拦截器链;
        1. list<Object> interceptorLIst保存所有的拦截器,这其中有一个ExposeInvocationInterceptor和其他的增强器;
        2. 遍历所有的增强器,将器转化为Intereceptor
        3. 将增强器转化成了list<MethodInterceptor>;转换完成之后返回一个MethodInterceptor数组;
      3. 如果没有拦截器链,也就是说他不被环绕,不被增强,那就直接执行目标方法;
      4. 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链的信息都传入,创建一个cglibMethidInvocation对像,并调用record()方法;
      5. 执行拦截器链

    5.拦截器的触发过程

    1.  如果没有拦截器、拦截器的索引或者拦截器数组大小未-1时、遍历拦截器的参数i增长到拦截器链长度时,会执行目标方法;
    2. 链式获取每一个拦截器,拦截器执行Invoke方法(这其实也在调用cglib的proceed()方法,让其继续获取下一个拦截器)

                每一个拦截器都会在下一个拦截器调用完成后才执行。

    applyBeanPostProcessorsBforeInitlization

  • 相关阅读:
    电话传递数据加密
    求一个3*3矩阵对角线元素之和
    ASP编程入门进阶(四):内置对象Request 详细出处参考:http://www.jb51.net/article/5887.htm
    ASP编程入门进阶(三):接触脚本程序 详细出处参考:http://www.jb51.net/article/5886.htm
    *****User controls in Winform can not be localized
    Regex字符串處理函數--Split--Replace
    office2007如何自动生成目录
    *****解決gridControl lookupedit click時為空的問題
    测试人员应具备的技能和素养
    eXpressApp Framework簡介
  • 原文地址:https://www.cnblogs.com/easilyai/p/9906868.html
Copyright © 2011-2022 走看看