【Spring4.0笔记整理十一】AOP详解

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/80465540

  已经有一个多星期没写博客了,上个星期在忙一个教学项目一直没顾上,今天才搞定。。

  AOP 和 IOC 他俩是 Spring 中的两大基石,IOC 我们之前已经讲解过了(详见:IOC与DI详解)。今天就来为大家讲解一下什么是 AOP。


本文分为三部分:

  一、常见的编程思想——POP、OOP、AOP

  二、为什么需要使用 AOP?

  三、AOP中的术语





一、常见的编程思想——POP、OOP、AOP

  AOP 它的专业名词叫做 面向切面编程,说的通俗一些,它就是一种编程的思想而已。说起编程思想,大家一定会想到 面向过程的编程思想(POP)面向对象的编程思想(OOP),而 AOP 其实是 OOP 衍生出来的一种思想而已,它是 OOP 的一种补充。我在这里为大家举个小例子,使大家能够更好的理解 POP、OOP 和 AOP。

  例如我们要开发一个五子棋的小游戏,如果我们用 POP 的思想去完成,那么步骤应该是这样的:

POP思想

  如果我们使用 OOP 的思想来完成,那么就变成了这样的:

  先来三个类,分别是:棋类、棋盘类、规则类。黑棋和白棋有行走的方法,棋盘有绘制的方法,规则有判断的方法。如下所示:

各类对象

  1、黑白双方,这俩方的行为是一模一样的,都可以行走;
  2、棋盘系统,负责绘制当前棋局的画面;
  3、规则系统,负责判定诸如犯规、输赢等。

  大家会发现 OOP的设计思路是这样的:

  第一类对象(棋类对象)负责行走,并告知第二类对象(棋盘对象)绘制当前棋盘局面,同时利用第三类对象(规则对象)根据当前棋盘的局面判断输赢。

  从上面我们可以很明显的看出,OOP是以功能来划分问题,而不是步骤

  其实 OOP 比 POP 最大的好处就在于可以对系统有很好的扩展性和维护性。例如,我觉得现在的规则不好,我需要重新制定一个新的规则,那么我可以直接在规则类中添加一个新的规则方法,然后调用它就可以了。

  假如我现在又多了一个需求,我需要记录一下每个阶段绘制棋盘局面和判断输赢的时间,也就是在绘制棋盘局面的前面加一个时间日志和在判断输赢的前面加一个时间日志,那么如果用 OOP 的思想,应该是这样实现的:

加日志

  不知道大家有没有疑问,这两个时间日志都是一样的,那么我们能不能把它提取出来,来减少代码的重用呢?我们以前的做法是这样的,添加一个日志类,然后在棋盘类和规则类中调用日志类中的方法就可以了,如下所示:

日志模块

  但是这样做还存在一个问题,它们的耦合度变高了,也就是类和类之间的联系越来越紧密了,如果日志类发生异常,势必会影响到棋盘类和规则类,这样做显然是不好的。就在这时候有人提出我们能不能不在棋盘类和规则类中调用,直接在代码运行时将这个时间日志动态的加到棋盘类和规则类中呢?这显然是不可能实现的,因为我们都知道 java 程序在运行的时候是不能改变程序结构 的。

  为了解决这个看似不可能完成的事情,程序员们祈求上天,日益加班,以诚感动天,终于把老天感动了,在一个闪电交加的夜晚,从天而降一把大刀,这把大刀锋利无比,传说它能够在程序运行中横向切割代码。

  到底是不是这样呢?我们可以将一个类中的代码看成一团面,用 AOP 这把大刀在煮面的时候横向把这团面切开,并且往里面加入一些调料,然后使用 AOP神功将这团面缝合住,让人完全看不出一点破绽。我们把这个过程叫做横向切面,这其实就是 AOP,先不把日志类中的方法写到棋盘类和规则类中,但在程序运行的时候动态的将时间日志加进去,这样是不是就能把耦合度降低了呢?

  对于新手来说,我们先不必了解 AOP 的神奇过程,只需知道它能在程序运行的时候切开代码并可以往进加一些代码就行了,AOP 最重要的目的是要解耦!如果你想了解它的实现原理,那你可以去看看代理设计模式,AOP其实是代理设计模式的一个典型应用,在这里不作过多讲解。

  一句话概括 AOP:它就是在程序运行的时候动态的改变程序结构的一种技术,也是一种新的编程思想。

二、为什么需要使用 AOP?

  在上文我们也提到了,它就是一种新的编程思想,它采取 横向切割 的机制,取代了传统 纵向继承 体系重复性代码。AOP 是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。我们看一下这句话中的几个关键词:

  第一个是 “动态代理技术”,这个就是 Spring AOP 实现底层的技术,底层使用的是动态代理模式。

  第二个是 “不修改源代码”,这个就是 AOP 最关键的地方,也就是我们平时所说的非入侵性。。

  第三个是 “添加功能”,不改变原有的代码,为程序添加功能。


三、AOP中的术语

  网络上有很多关于AOP术语的讲解特别专业,大家基本上都是一个版本复制来复制去的,所以我今天好好把这几个常见的术语讲解一下(关注点、目标对象、代理对象、切面、通知/增强器、连接点、切入点、织入),大家要明白其中的意思:

  • 关注点(Concem): 我们要关注的问题,比如在上面那个 “五子棋” 例子中,我们要关注的问题是在 “绘制棋盘” 方法 和 “判断输赢”方法 前加一个 “时间日志”,这就是一个关注点。

关注点

  • 目标对象(Target): 没有加入日志的棋盘类和规则类。
  • 代理对象(Proxy): 在运行的时候加入日志的棋盘类和规则类。
  • 切面(Aspect): 又叫方面,就是一个关注点的模块,比如我们对 棋盘类 和 规则类 中的时间日志单独拿出来并封装成一个 日志模块,那么这个日志模块就是一个切面。

切面&目标对象&代理对象

  • 通知/增强器(Advice): 就是在运行的时候放入到目标对象中的程序代码,这段代码就是一个增强器,比如在运行 棋盘类和规则类的时候,将 时间日志 方法放入到绘制 方法 和 判断方法的这段代码就是增强器。
  • 连接点(Joinpoint): 在目标对象中的一个标记,在运行的时候会根据这个标记放入对应的切入点。
  • 切入点(Pointcut): 就是切面中的要放入目标对象中的方法,比如上面 日志模块中的 时间日志方法就是一个切点。

增强器&切入点&连接

  • 织入(Weaving): 是将切入点和增强器合起来放入到运行状态中的过程。

      这个词70后以前的大叔大妈是比较熟悉的,也不知道作者是怎么想的,竟然能联想到织布。AOP 像一台织布机,将目标中的切入点和增强器通过 AOP 这台织布机天衣无缝地编织到一起。根据不同的实现技术,AOP 有三种织入的方式:

      a、编译期织入,这要求使用特殊的Java编译器。
      b、类装载期织入,这要求使用特殊的类装载器。
      c、动态代理织入,在运行期为目标类添加增强器生成子类的方式。

      Spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。




猜你喜欢

转载自blog.csdn.net/sun8112133/article/details/80465540