0
点赞
收藏
分享

微信扫一扫

第7章 一起来看AOP

kmoon_b426 2022-04-07 阅读 22
springjava

第7章 一起来看AOP

本章内容

  • AOP的尴尬
  • AOP走向现实
  • Java平台上的AOP实现机制
  • AOP国家的公民

AOP全称为Aspect-Oriented Programming,中文通常翻译为面向切面编程。

日志记录、安全检查、事务管理等系统需求就像一把把刀横切到我们组织良好的各个业务功能模块之上(见图7-3)。以AOP的行话来说,这些系统需求是系统中的横切关注点(cross-cuting concern)。

image-20220405194125430

使用传统方法,我们无法更好地以模块化的方式,对这些横切关注点进行组织和实现。所以AOP引入了Aspect的概念,用来以模块化的形式对系统中的横切关注点进行封装。Aspect之对于AOP,就相当于Class之对于OOP。我们说过AOP仅是对OOP方法的一种补足,当我们把以Class形式模块化的业务需求和以Aspect形式模块化的系统需求拼装到一起的时候,整个系统就算完成了。

AOP的尴尬

AOP必须依靠OOP。

AOP走向现实

AOP是一种理念,需要某种语言以帮助实现相应的概念实体,我们称之为AOL(Aspect-Oriented Language)。AOL可以与系统实现语言相同,也可以不同,例如AspectJ是用于拓展Java的一种AOL,但它并不是使用java来编写的。

囿于现实中AOP技术实现上的尷尬,AOL实现的AOP各个概念实体,最终都需要某种方式集成到系统实现语言所实现的OOP实体组件中。所以,系统实现语言通常称为系统中使用的AOL的“寄生语言”,而将AO组件集成到OOP组件的过程,在AOP中称之为织入(Weave)过程。

将AOP的Aspect织入到OOP系统的实现方式可谓千差万别。但不管如何实现,织入过程是处于AOP和OOP的开发过程之外的,而且对于整个系统的实现是透明的,开发者只需要关注相应的业务需求实现,或者系统需求的实现即可。当所有业务需求和系统需求以模块化的形式开发完成之后,通过织入过程就可以将整个的软件系统集成并付诸使用。

我们来看一下Java界的AOP框架的历史。

静态AOP时代

静态AOP,即第一代AOP,以最初的Aspect为杰出代表,其特点是,相应的横切关注点以Aspect形式实现之后,会通过特定的编译器,将实现后的Aspect编译并织入到系统的静态类中。

静态AOP的优点是,Aspect直接以Java字节码的形式编译到Java类中,Java虚拟机可以像通常一样加载Java类运行(因为编译完成的Aspect是完全符合Java类的规范的),不会对整个系统的运行造成任何性能损失。

缺点嘛,就是灵活性不够。如果横切关注点需要改变织入到系统的位置,就需要重新修改Aspect定义文件,然后使用编译器重新编译Aspect并重新织入到系统中。

动态AOP时代

也称为第二代AOP,AspectJ也引入了动态织入的行为。第二代AOP的AOL大都采用java语言实现,AOP的织入过程在系统运行开始之后进行,而不是预先编译到系统中,而且织入信息大都采用外部XML文件格式保存,可以在调整织入点以及织入逻辑单元的同时,不必变更系统其他模块甚至在系统运行时,动态改变织入逻辑

但动态AOP在引入灵活性以及易用性的同时,也会不可避免地引入相应的性能问题。因为动态AOP的实现产品大都在类加载或者系统运行期间,采用对系统字节码进行操作的方式来完成Aspect到系统的织入,难免会造成一定的运行时性能损失。但随着JVM版本的提升,对反射以及字节码操作技术的更好支持,这样的性能损失在逐渐减少,大多数情况下,这种性能损失是可以容忍的。

Java平台上的AOP实现机制

动态代理

可以在运行期间,为相应的接口(Interface)动态生成对应的代理对象。

我们可以将横切关注点逻辑封装到动态代理的InvocationHandler中,然后在系统运行期间,根据横切关注点需要织入的模块位置,将横切逻辑织入到相应的代理类中,以动态代理为载体的横切逻辑,就可以与系统其他模块一起工作了。

优缺点:所有需要织入横切关注点逻辑的模块都得实现相应的接口,因为动态代理机制只针对接口有效

动态字节码增强

为需要织入横切逻辑的模块类在运行期间,通过动态字节码增强技术,为这些系统模块类生成相应的子类,将横切逻辑加到这些子类中,让应用程序在执行期间使用的是这些动态生成的子类,从而达到将横切逻辑织入系统的目的。

优点:即使模块类没有实现相应的接口,依然可以对其进行扩展。

缺点:如果需要扩展的类或者类中的方法声明为final的话,则无法对其子类化的扩展。

自定义类加载器

所有的java程序的class都要通过相应的类加载器(Classloader)加载到Java虚拟机之后才可以运行。默认的类加载器会读取class字节码文件,然后按照class字节码规范,解析并加载这些class文件到虚拟机运行。如果能够在这个class文件加载到虚拟机运行期间,将横切逻辑织入到class文件也可以的

AOP中的相关概念

JoinPoint 连接点

在系统运行之前,AOP的功能模块都需要织入到OOP的功能模块中。所以,要进行这种织入过程,我们需要知道在系统的哪些执行点上进行织入操作,这些将要在其之上进行织入操作的系统执行点就称之为Joinpoint

为了便于理解,我们看下图7-6中的比较一般的程序流程图:

image-20220405202249630

常用的joinPoint类型:

  • 方法级别的调用(MethodCall),某个方法被调用时候所处的程序执行点。

  • 方法调用执行(MethodCallexecution),某个方法内部执行开始时点。

  • 构造方法执行

  • 字段设置/获取(set/get)

  • 异常处理执行

  • 类初始化

Pointcut 切点

表示一组jointpoint,这些jointpoint或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的Advice将要发生的地方。

Advice 增强

Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过before、after和around来区别是在每个 joint point 之前、之后还是代替执行的代码。

Aspect 切面

Aspect声明类似于Java中的类声明,在Aspect中会包含着一些Pointcut以及相应的Advice。

Weaving 织入

Aspect 和其他对象连接起来, 并创建 Adviced object 的过程,即完成横切关注点逻辑到系统的最终织入。

Target Object 目标对象

符合Pointcut所指定的条件,将在织入过程中被织入横切逻辑的对象,成为目标对象(Target Object)。

当把所有这些概念组织到一个场景之后,我们脑海中应该有这么一幅图。

image-20220405212439621

解释下图片:贷款申请、贷款管理、入出金管理这些是我们系统中普通的业务需求,现在需要为这些业务需求上加入其他系统功能,即横切逻辑。

那么此时这几个业务需求就是JoinPoint连接点,Advice增强是我们想加入的其他系统功能,这些JointPoint连接点(在哪加功能)和Advice增强(加什么功能)就是Aspect切面。

织入器拿到这个Aspect切面后,会根据Pointcut切点找到对应的Joinpoint连接点,再将相应的Advice增强织入到Joinpoint连接点上。

本章小结

本章介绍了AOP的背景、Java平台上AOP实现的机制和AOP中的相关概念,在此基础上,我们再开始真正的Spring AOP之旅。

举报

相关推荐

0 条评论