从零开始的实习——Spring——AOP初识

从OOP到AOP

从过程化的编程到面向对象编程OOP,我们一直在找到更加完美的开发方法。当OOP/OOSD(Object-Oriented Software Development)被提出来,以取代过去的面向过程的编程方法时,或许那时候的人们认为这是一直所追求的那颗“银弹”。但是,不得不承认的是,即使是OOP,依然不能很好的解决所有问题。
使用OO,我们可以对业务需求等普通关注点进行很好的抽象和封装,但是对于系统需求而言,情况却有所不同。
对于CREDIT项目为例,它是一个有关贷款业务的管理系统。从业务角度来说,该系统提供了顾客贷款申请、顾客信息管理、贷款信息管理等功能,这些都是普通的业务需求
不过,在开发中为了调试,或者进入生产环境后为了对系统进行监控,我们需要为这些业务需求的实现对象添加日志记录功能。这些则属于系统需求的范围
从零开始的实习——Spring——AOP初识_第1张图片
对于普通的业务关注点,OOP可以很好的对其分解并模块化,但是却无法避免系统需求的实现在系统中各处产生的散落问题。
这时就引入了AOP:
AOP全称Aspect-Oriented Programming,即面向切片编程。使用AOP,我们可以对类似于Logging和Security等系统需求进行模块化的组织,简化系统需求与实现之间的对比关系,进而使得整个系统的实现更具模块化。
Aspect之于AOP就像Class之于OOP
从零开始的实习——Spring——AOP初识_第2张图片
横向切片,纵向模块。
这是两个不同的空间,通过OOP的空间结合AOP的空间就可以构建出一个完美的系统。
** AOP的尴尬**
不过,由于当时的技术缺陷,完美可以构造出AOP的一片一片的切片,却无法构建出AOP独有的空间。也就是AOP的实现需要寄生在OOP的主权领土中。

AOP走向现实

AOP是一种历年,要实现这种理念也需要一种现实的方式,就像OOP需要相应的语言支持一样。
我们把实现AOP的语言叫做AOL。AOL可以与系统实现语言相同,比如OOP用的java,那么AOL也可以为java。但是也可以不同,比如AspectJ是扩展自Java的一种AOL。
静态AOP
也就是第一代AOP,以最初的AspectJ为代表,其特点是横切关注点以Aspect形式实现后,会通过特定点一起,将实现后的Aspect编译并织入到系统的静态类中。比如AspectJ会使用ajc编译器将各个Aspect以Java字节码的形式编译到系统的各个功能模块中,以达到融合Aspect和Class的目的。
静态AOP的优点就是:直接以Java字节码的形式编译到Java类中,Java虚拟机可以像通常一样加载Java类运行。
缺点就是:灵活性不够,如果横切关注点需要改变织入系统的位置,就需要重新修改Aspect定义文件,然后使用编译器重新Aspect并重新织入到系统中。
动态AOP
也是第二代AOP。这代AOP大都通过Java语言提供的各种动态特性来实现Aspect织入到当前系统的过程,比如JBoss AOP,Spring AOP以及Nanning等框架。
第二代AOP的AOL大多采用Java实现,所以很容易开发和集成,Aspect与Class一样最终以Class身份作为系统的一等公民存在,与静态AOP最大的不同就是,AOP的织入过程是系统运行开始之后进行的,而不是预先编译到系统类中,而且织入信息大都由外部XML文件格式保存,可以很灵活的调整织入点和修改织入逻辑。缺点就是,难免会对系统的性能造成一定的损失,不过这个损失是可以容忍的。

Java平台上的AOP实现机制

动态代理
可以在运行期间,为相应的接口动态生成代理对象。
动态字节码增强
我们知道,java虚拟机加载的class文件都是符合一定规范的,这样程序运行就不会有问题。通常的class文件都是从Java源代码文件使用javac编译器编译成的,但是只要符合java class规范,我们也可以使用ASM或者CGLIB等java工具库,在程序运行期间,动态构建字节码的class文件。
自定义类加载器
所有java程序的class都要通过相应的类加载器(ClassLoader)加载到Java虚拟机之后才可以运行。默认的类加载器会读取class字节码文件,然后按照class字节码规范,解析并加载这些class文件到虚拟机运行,如果我们能够在这个class文件加载到虚拟机运行期间,横切逻辑织入到class文件的话,是不是就完成了AOP和OOP的融合呢?
AOL拓展
采用拓展的AOL,在AOP概念的表述上颇具实力。

你可能感兴趣的:(从零开始的实习——Spring——AOP初识)