8.4 Spring的AOP 8.4.1 为什么需要AOP
8.4 Spring的AOP
AOP(Aspect Orient Programming)
,也就是面向切面编程,作为面向对象编程
(OOP
)的一种补充,已经成为一种比较成熟的编程方式。AOP
和OOP
互为补充,面向对象编程将程序分解成各个层次的对象,而面向切面编程将程序运行过程分解成各个切面。可以这样理解:
- 面向对象编程是从静态角度考虑程序结构,
- 面向切面编程则是从动态角度考虑程序运行过程.
8.4.1 为什么需要AOP
在传统的OOP
编程里以对象为核心,整个软件系统由一系列相互依赖的对象组成,而这些对象将被抽象成一个个类,并允许使用类继承来管理类与类之间一般到特殊的关系。随着软件规模的增大,应用的逐渐升级,慢慢出现了一些OOP
很难解决的问题。
面向对象可以通过分析抽象出一系列具有一定属性与行为的类,并通过这些类之间的协作来形成个完整的软件功能。由于类可以继承,因此可以把具有相同功能或相同特性的属性抽象到一个层次分明的类结构体系中。随着软件规范的不断扩大,专业化分工越来越细致,以及OOP
应用实践的不断增多随之也暴露出了一些OOP
无法很好解决的问题.
现在假设系统中有三段完全相同的代码,这些代码通常会采用”复制”、”粘贴”的方式来完成,通过这种”复制”、”粘贴”的方式开发出来的软件示意图如图8.3所示。
看到如图8.3所示的示意图,可能有的读者已经发现了这种做法的不足之处—如果有一天,图8.3中的深色代码段需要修改,那是不是要打开三个地方的代码进行修改?如果不是三个地方包含这段代码而是100个地方,甚至是1000个地方包含这个代码段,那会是什么后果?
为了解决这个问题,通常会将如图8.3所示的深色代码部分定义成一个方法,然后在三个代码段中分别调用该方法即可。在这种方式下,软件系统的结构示意图如图8.4所示。
对于如图8.4所示的软件系统,如果需要修改深色代码部分,只要修改一个地方即可。不管整个系统中有多少个地方调用了该方法,程序无须修改这些地方,只需修改被调用的方法即可—通过这种方式,大大降低了软件后期维护的复杂度。
对于如图8.4所示的方法1、方法2、方法3依然需要显式调用深色方法,这样做能够解决大部分应用场景。如果程序希望实现更好的解耦,希望方法1、方法2、方法3彻底与深色方法分离——方法1、方法2、方法3无须直接调用深色方法,那该如何解决?
因为软件系统需求变更是很频繁的事情,系统前期设计方法1、方法2、方法3时只实现了核心业务功能,过了一段时间,可能需要为方法1、方法2、方法3都增加事务控制;又过了一段时间,客户提出方法1、方法2、方法3需要进行用户合法性验证,只有合法的用户才能执行这些方法;又过了段时间,客户又提出方法1、方法2、方法3应该增加日志记录…面这样的情况,应该怎么处理呢?通常有两种做法。
- 根据需求说明书,直接拒绝客户要求。
- 拥抱需求,满足客户的需求
第一种做法显然不好,客户是上帝,开发者应该尽量满足客户的需求。通常会釆用第二种做法,那如何解决呢?是不是每次都先定义一个新方法,然后修改方法1、方法2、方法3的源代码,增加调用新方法?这样做的工作量也不小啊!此时就希望有一种特殊的方式:只要实现新的方法,然后无须在方法1方法2、方法3中显式调用它,系统会”自动”在方法1、方法2、方法3中调用这个特殊的新方法。
上面的自动执行的”自动”被加上了引号,是因为在编程过程中,没有所谓自动的事情,任何事情都是代码驱动的。这里的自动是指无须开发者关心,由系统来驱动。
上面的想法听起来很神奇,甚至有一些不切实际,但其实是完全可以实现的,实现这个需求的技术就是AOP
。AOP
专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在Java EE
应用中,常常通过AOP
来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP
已经成为一种非常常用的解决方案。