《Spring AOP的设计和实现方式》

AOP 的概念(Aspect Oriented Programming 面向方面/切面编程)

在了解Spring的AOP之前,我们先对AOP有一个简单的认识。

维基百科的解释:

面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计、观点导向编程、剖面导向程序设计)是计算机科学中的一个术语,指一种程序设计范型。该范型以一种称为侧面(aspect,又译作方面)的语言构造为基础,侧面是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点(crosscutting concern)。

侧面的概念源于对面向对象的程序设计的改进,但并不只限于此,它还可以用来改进传统的函数。与侧面相关的编程概念还包括元对象协议、主题(subject)、混入(mixin)和委托。

“面向侧面的程序设计”(aspect-oriented programming)这一术语出现的具体时间已经不可考证了,但该词是由施乐帕洛阿尔托研究中心的Chris Maeda首先提出的。术语“横切”(crosscutting)是由Gregor Kiczales提出的。


来自百度的解释:

“面向切面编程”,这样的名字并不是非常容易理解,且容易产生一些误导。笔者不止一次听到类似“OOP/OOD11即将落伍,AOP是新一代软件开发方式”这样的发言。显然,发言者并没有理解AOP的含义。Aspect,没错,的确是“方面”的意思。不过,华语传统语义中的“方面”,大多数情况下指的是一件事情的不同维度、或者说不同角度上的特性,比如我们常说:“这件事情要从几个方面来看待”,往往意思是:需要从不同的角度来看待同一个事物。这里的“方面”,指的是事物的外在特性在不同观察角度下的体现。而在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。所以笔者更倾向于“面向切面编程”的译法。
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。


Spring AOP 的设计

以下来自官方文档资料翻译后:

Spring AOP 中的术语

在Spring AOP中,官方为了使用者更好的理解,使用了更为广泛的AOP术语,因为如果使用Spring自己的AOP术语,那将使理解将变得更加困惑.

  • 切面:模块化的关注点,横跨多个类。事务管理是企业Java应用程序中横切关注点的一个很好的例子。在Spring AOP中,使用正则类(the schema-based approach)或用@方面注释(@ AspectJ风格)注释的正则类来实现方面。

  • 切入点:程序执行过程中的一个点,例如执行方法或处理异常。在Spring AOP中,切入点总是表示方法执行。

  • 通知:一个方面在特定连接点上采取的行动。不同类型的建议包括“周围”、“前”和“后”的通知。(下面讨论了通知类型)。许多AOP框架,包括Spring,将一个通知作为拦截器建模,在连接点周围保持一个拦截器链。

  • Pointcut:一个匹配连接点的Spring专属词语。通知与切入点表达式相关联,并在切入点匹配的任何连接点上运行(例如,具有特定名称的方法的执行)。由切入点表达式匹配的连接点的概念是AOP的核心,Spring 默认使用AspectJ切入点表达式语言。

  • 引言:声明类型的附加方法或字段。Spring AOP允许您向任何建议的对象引入新的接口(以及相应的实现)。例如,您可以使用介绍使bean实现一个ISAdvices接口,以简化缓存。(引言在AspectJ社区中称为类型间声明)。

  • 目标对象:由一个或多个方面建议的对象。也称为建议对象。由于使用运行时代理来实现Spring AOP,因此该对象将始终是代理对象。

  • AOP代理:AOP框架创建的对象,用于实现方面合同(建议方法执行等)。在Spring框架中,AOP代理将是JDK动态代理或CGLIB代理。

  • 执行契机:其他应用程序类型或对象链接方面,以创建建议对象。这可以在编译时(例如使用AspectJ编译器)、加载时或在运行时完成。Spring AOP和其他纯Java AOP框架一样,在运行时进行相应的操作。


通知的类型

  • 在通知之前:在连接点之前执行的通知,但它没有能力阻止执行流进入连接点(除非抛出异常)。

  • 在返回通知之后:在连接点完成之后要执行的通知:例如,如果一个方法返回而不引发异常。

  • 投掷通知:如果一个方法通过抛出异常退出,则要执行通知。

  • (最后)通知:不管连接点退出的方式(正常或异常返回),要执行的通知。

  • 围绕通知:围绕一个连接点的通知,比如方法调用。这是一个功能最丰富的通知。环绕通知可以在方法调用之前和之后执行自定义行为。它还负责选择是否返回到连接点,或者通过返回自己的返回值或抛出异常来快捷地执行通知的方法。


Spring AOP 的实现

Spring AOP 使用了JDK动态代理和CGlib代理两种方式实现,我们项目中默认使用的是使用JDK动态代理来实现的

JDK动态代理

主要使用到 InvocationHandler 接口和 Proxy.newProxyInstance() 方法。JDK动态代理要求被代理实现一个接口,只有接口中的方法才能够被代理。其方法是将被代理对象注入到一个中间对象,而中间对象实现InvocationHandler接口,在实现该接口时,可以在 被代理对象调用它的方法时,在调用的前后插入一些代码。而 Proxy.newProxyInstance() 能够利用中间对象来生产代理对象。插入的代码就是切面代码。所以使用JDK动态代理可以实现AOP。

CGlib代理

字节码生成技术实现AOP,其实就是继承被代理对象,然后Override需要被代理的方法,在覆盖该方法时,自然是可以插入我们自己的代码的。因为需要Override被代理对象的方法,所以自然CGLIB技术实现AOP时,就必须要求需要被代理的方法不能是final方法,因为final方法不能被子类覆盖。

更多详细内容参考:https://www.cnblogs.com/digdeep/p/4528353.html

原文地址:https://www.cnblogs.com/lvgo/p/13275828.html