软件开发的目的是为了解决各种需求,包括业务需求和系统需求。目前,业界通过使用面向对象的编程思想,已经可以对业务需求等普通关注点进行很好的抽象与封装,并且使之模块化。但是对于系统需求一类的关注点来说,情况却有所不同。对于业务需求而言,需求与其具体实现之间的关系基本上是一对一的。我们可以在系统中的某一个确定的点找到针对需求的实现,无论是开发还是维护,都比较方便。但是系统需求,比如记录日志、事务管理等系统需求,它们往往在系统的各处散落。我们需要找到一种更好的方式来解决这类系统需求,这种软件开发模式就是面向切面编程,也就是AOP。
我们可以发现,任何一个软件系统,其中的日志记录、安全检查、事务管理等系统需求就像一把刀,横切到我们系统中各个业务功能模块之上。在AOP的行话中,这些系统需求是系统中的横切关注点。在AOP中,是使用Aspect的概念来对横切关注点进行封装。Aspect至于AOP,就相当于Class至于OOP。我们应该明白,AOP仅仅是OOP方法的一种补足,但我们把以Class形式模块化的业务需求和以Aspect形式模块化的系统需求拼接转到一起的时候,整个系统功能就完整了。
在对整个系统进行分析之后,我们可以将不同的需求实现为Aspect类型和Class类型的两种积木,他们拼装到一起才能组成一个功能完整的系统。但是两个积木空间并不是等同的,限于当前的技术,Aspect积木空间不能独立构建,AOP没有主权,现有的AOP实现都需要“寄生”于OOP的主权领土上。AOP作为一种概念,同样需要实现方式,AOP也需要某种语言帮助实现相应的概念实体,我们统称这些实现AOP的语言为AOL。AOL可以与系统实现语言一致,比如JAVA,也可以是自己的语言,比如AspectJ等。AOL实现的AOP各个概念实体,最终都要以某种模式集成到系统实现语言所实现的OOP实体组件中。把AOP组件集成到OOP组件的过程,在AOP中称之为织入过程。
AOP的发展进程可以简单地分成两代:第一代是静态AOP时代,相应的横切关注点以Aspect形式实现之后,通过特定编译器将Aspect编译并织入到系统的静态类中;第二代是动态AOP时代,通过使用Java语言提供的各种动态特性来实现Aspect织入到当前系统的过程。在Java平台上,AOP发展到今天,主要使用的AOP实现机制有:
+ 动态代理
+ 动态字节码增强
+ Java代码生成
+ 自定义类加载器
+ AOL扩展
可以看到这五种实现AOP的方式,其中有些已经过时,他们之间的优缺点可以根据本身的机制推导出来。 AOP作为一种编程思想的概念,其中包含有较多的细节概念,在深入学习AOP实现之前,我们必须先熟悉熟悉。
+ Joinpoint 可以进行织入的系统执行点
+ Pointcut Joinpoint的表达方式(直接指定方法名称、正则表达式、特定Pointcut表述语言)
+ Advice 单一横切关注点逻辑的载体,代表将会织入到Joinpoint的横切逻辑(Before Advice、After Advice(After returning、After throwing、After Finally)、Around Advice、Introduction
+ Aspect 对横切关注点逻辑进行模块化封装的AOP概念实体(可包含多个Pointcut以及相关Advice定义)
+ 织入和织入器 只有经过织入,以Aspect模块化的横切关注点才会集成到OOP现存系统中。(AspectJ使用专门编辑器ajc、JBoss AOP使用自定义类加载器、Spring AOP使用一组类,最常用ProxyFactory)
+ 目标对象 符合Pointcut所指条件,将被织入横切逻辑的对象
AOP是近年来流行起来的一种软件开发模式,本文都Java平台上的各种AOP框架及产品的实现原理和方式进行了简单地剖析,希望对理解AOP的现状有一个总体的认识。