Spring AOP 剖析(2)
Java 平台上 AOP 的实现机制
1. 动态代理
?
JDK1.3之后,引入了动态代理 —ynamic Proxy)机制,可以在运行期间,为相应的接口(Interface)动态生成对应的代
?
理对象,所以可以将横切关注点逻辑封装到动态代理的 InvocatioHandler 中,然后在系统运行期间,根据横切关注点需要织
?
入的模块位置,将横切逻辑织入到相应的代理类中。 以动态代理类为载体的横切逻辑,现在当然就可以与系统的其他模块一起
?
工作了。
?
?
缺点或是优点:所有需要织入横切关注点逻辑的模块类都得实现响应的接口,因为动态代理机制只针对接口有效。
?
Spring AOP 默认情况下采用这种机制实现 AOP 机能。
?
?
2. 动态字节码增强
?
Java虚拟机加载的 Class 文件都是符合一定规范的,所以,只要交给 Java 虚拟机运行的文件符合 Java Class 规范,
?
程序的运行就没有问题。 通常的 class 文件都是从 Java 源代码文件只用 Javac 编译器编译而成的,但是只要符合 Java
?
class 规范,也可以使用 ASM 或者 CGLIB 等 Java 工具库,在程序运行期间,动态构建字节码的 class 文件
?
?
?
在这样的前提下,可以为需要织入横切逻辑的模块类在运行期间,通过字节码增强技术,为这些系统系统模块类生成
?
相应的子类,而将横切逻辑加到这些子类中,让应用程序在执行期间使用的是这些动态生成的子类,从而达到将横切逻辑
?
织入系统的目的。
?
?
优点:即使模块类没有实现相应的接口,依然可以对其进行扩展,而不用像动态代理那样受限于接口。
缺点:如果需要扩展的类以及类中的实例方法声明为 final ,则无法对其进行子类化扩展
?
Spring AOP 在无法采用动态代理机制进行 AOP 功能扩展的时候,会使用 CGLIB 库的动态字节码增强支持来实现 AOP 的功能扩展
?
3.? Java 代码生成? (早期 EJB 使用,现在已经退休了)
?
大概就是 EJB 容器根据部署描述符文件提供的织入信息,会为相应的功能模块类生成对应的 Java 代码,然后通过部署工具编译 Java 代码生成相应的 Java 类。之后,部署到 EJB 容器的功能模块就可以正常工作了。
?
?
4. 自定义类加载器
?
所有的 Java 程序的 class 都要通过相应的 类加载器 (Classloader)加载到 Java 虚拟机之后才可以运行。默认的
?
类加载器会读取 class 字节码文件,然后按照 class 字节码规范,解析并加载这些 class 文件到虚拟机运行。如果能够在
?
这个 class 文件加载到虚拟机运行期间,将横切逻辑织入到 class 文件的话,就可以完成 AOP 与 OOP 的融合了。
?
?
可以通过自定义类加载器的方式完成横切逻辑到系统的织入,自定义类加载器通过读取外部文件规定的织入规则和必要
?
信息,在加载 class 文件期间就可以将横切逻辑添加到系统模块的现有逻辑中,然后将改动后的 class 交给 Java 虚拟机
?
运行。
?
优点: 可以对大部分类以及相应的实例进行织入,功能与之前的集中方式相比当然强大很多。
缺点: 最大的问题就是 类加载器 本身的使用。某些应用服务器会控制整个类加载体系,所以,在这样的场景下使用可能会造成一定的问题。
?
?
JBoss AOP 和 AspectWerkz 框架都是采用自定义类加载器的方式实现, Spring AOP? 未采用该方式。
?
5. AOL 扩展
?
AOL 扩展是最强大,也最难掌握的一种方式,,AspectJ 就属于这种方式。AOP的各种概念在 AOL 中大都有一一对应的
?
实体。 可以使用扩展过的 AOL, 实现任何 AOP 概念实体甚至 OOP 概念实体, 比如 Aspect 以及 Class。 所有的
?
AOP 概念在 AOL 中得到了最完美的表达。
?
缺点: 该方式强大的代价就是,需要重新学习一门扩展了旧有语言的 AOL 或者全新的 AOL 语言。
?
Spring AOP 未采用该方式
?
?