AOP底层原理

内容纲要

容器是OOP的高级工具(自上而下)

以低耦合低侵入的方式打通从上到下的开发通道

  • 按部就班填充代码逻辑实现业务功能,每层逻辑都可无缝替换
  • OOP将业务程序分解成各个层次的对象,通过对象联动完成业务
  • 无法很好地处理分散在各业务里的通用系统需求

开发人员需要关心的需求

  • 添加日志信息:为每个方法添加统计时间
  • 添加系统权限校验:针对某些方法进行限制
  • OOP下必须得为每个方法都添加通用的逻辑工作,增加维护成本

关注点分离 Concern Separation

不同的问题交给不同的部分去解决,每部分专注解决自己的问题

  • Aspect Oriented Programming就是其中一种关注点分离的技术
  • 通用化功能的代码实现即切面
  • AspectAspect之于AOP,就相当于Class之于OOP, Bean之于Spring

陆军(OOP)和空军(AOP)

AOP的子民们

  • 切面Aspect:将横切关注点逻辑进行模块化封装的实体对象
  • 通知Advice:好比是class里面的方法,还定义了织入逻辑的时机
  • 连接点Joinpoint,允许使用advice的地方(默认方法级别)
  • 切入点Pointcut :定义-系列规则对Joinpoint进行筛选
  • 目标对象Target :符合Pointcut条件,要被织入横切逻辑的对象

Advice

  • BeforeAdvice :在JoinPoint前被执行的Advice
  • AfterAdvice :好比ry.cach..finaly里面的finaly
  • AfterReturningAdvice :在Joinpoint执行流程正常返回后被执行
  • AfterThrowingAdvice : Joinpoint执行过程中抛出异常才会触发
  • AroundAdvice :在Joinpoint前和后都执行,最常用的Advice

单个Aspect的执行顺序

多个Aspect的执行顺序

order值越小,优先级越大

Introduction---引入型Advice

  • 为目标类引入新接口,而不需要目标类做任何实现
  • 使得目标类在使用的过程中转型成新接口对象,调用新接口的方法

AOP是OOP里的"寄生虫"

AOP需要OOP理解自己的语义,所以并不像单独使用这么灵活

  • 织入:将Aspect模块化的横切关注点集成到OOP里
  • 织入器:完成织入过程的执行者,如ajc
  • Spring AOP则会使用一组类来作为织入器以完成最终的织入操作

SpringAOP的实现原理

代理模式

寻求改进

溯源ClassLoader

  • 通过带有包名的类来获取对应class文件的二进制字节流
  • 根据读取的字节流,将代表的静态存储结构转化为运行时数据结构
  • 生成一个代表该类的Class对象,作为方法区该类的数据访问入口

改进的切入点

根据一定规则去改动或者生成新的字节流,将切面逻辑织入其中

  • 行之有效的方案就是取代被代理类的动态代理机制
  • 根据接口或者目标类,计算出代理类的字节码并加载到JVM中去

SpringAop的实现原理之JDK动态代理

  • 程序运行时动态生成类的字节码,并加载到JVM中.
  • 要求[被代理的类]必须实现接口
  • 并不要求[代理对象]去实现接口,所以可以复用代理对象的逻辑
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy

代码示例

SringAOP的实现原理之CGLIB动态代理

代码生成库: Code Generation Library

  • 不要求被代理类实现接口
  • 内部主要封装了ASM Java字节码操控框架
  • 动态生成子类以覆盖非final的方法,绑定钩子回调自定义拦截器

JDK动态代理和CGLIB

实现机制

  • JDK动态代理:基于反射机制实现,要求业务类必须实现接口
  • CGLIB :基于ASM机制实现,生成业务类的子类作为代理类
    JDK动态代理的优势
  • JDK原生,在JVM里运行较为可靠
  • 平滑支持JDK版本的升级
    CGLIB的优势
  • 被代理对象无需实现接口,能实现代理类的无侵入

SpringAop的底层机制

  • CGLIB和JDk动态代理共存
  • 默认策略:Bean实现接口则JDK,否则使用CGLIB

AspectJ框架

提供了完整的AOP解决方案,是AOP的Java实现版本

  • 定义切面语法以及切面语法的解析机制
  • 提供了强大的织入工具

    AspectU框架的织入时机:静态织入和LTW
  • 编译时织入:利用ajc ,将切面逻辑织入到类里生成class文件(静态)
  • 编译后织入:利用ajc ,修改javac编译出来的class文件(静态)
  • 类如载期织入:利用java agent ,在类加载的时候织入切面逻辑(LTW)

Spring AOP2.0

仅仅用到了AspectJ的切面语法,并没有使用ajc编译工具

  • 避免增加用户的学习成本
  • 只是默认不使用,如果想用ajc还是可以引入的
  • 织入机制沿用自己的CGLIB和JDK动态代理机制

SpringAOP的总体流程

  • 注册解析AOP的服务
  • 解析和加载横切逻辑
  • 将横切逻辑织入目标Bean中
THE END
分享
二维码
< <上一篇
下一篇>>