Spring AOP 剖析(2)

Java 平台上 AOP 的实现机制


1. 动态代理

JDK1.3之后,引入了动态代理 (Dynamic 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 语言。

S pring AOP 未采用该方式

猜你喜欢

转载自pengranxiang.iteye.com/blog/1622162
今日推荐