Spring AOP学习笔记(一):基础概念

AOP产生背景

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

我们在开发的过程中会对软件开发进行抽象、分割成各个模块或对象。例如,我们会对API进行抽象成四个模块:Controller,Service,Gateway,Command.这很好地解决了业务级别的开发,但对于系统级别的开发我们很难聚焦。比如、对于每一个模块需要进行打日志、代码监控、异常处理。以打日志为例,我只能将日志代码嵌套在各个对象上,而无法关注日志本身,而这种现象又偏离了OOP思想。

Spring AOP学习笔记(一):基础概念
Spring AOP学习笔记(一):基础概念
为了能够更好地将系统级别的代码抽离出来,去掉与对象的耦合,就产生了面向AOP(面向切面)。如上图所示,OOP属于一种横向扩展,AOP是一种纵向扩展。AOP依托于OOP,进一步将系统级别的代码抽象出来,进行纵向排列,实现低耦合。

AOP应用场景

AOP在系统开发中应用非常广泛,常见场景如下:

  • 事务处理
  • 日志处理
  • 异常处理
  • 权限控制
  • 系统性能监控
  • 其他

AOP的基本概念

AOP核心概念

  1. Join point(连接点):可以被切入的点,但不一定被切入。名词
  2. Point cut(切点):该切入哪些Join point。形容词
  3. Advice(通知):切入后做什么。比如打日志,权限管理,等等。动词
  4. Aspect(切面): Aspect 是Point cut与Advice的组合。在哪些点切入,切入后做什么

关于Join point和Point cut的区别

Spring AOP学习笔记(一):基础概念

可以理解为Point cut为形容词,而Join point为名词。被切入的都是符合Point cut描述的Join point。

上面是关于AOP中几个基本概念的定义,下面看下有关我们使用时的一些概念:

其他概念

  1. Target(目标对象):业务中需要被织入的具体对象。
  2. AOP proxy(AOP代理):Proxy即代理,并不属于AOP的成员,但却是整个AOP的具体实施者。在 Spring AOP 中, 一个 AOP 代理是一个 JDK 动态代理对象或 CGLIB 代理对象。
  3. Weaving(织入):就是整个AOP的过程,这个过程就叫做Weaving。

Weaving(织入)有三种方式:

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

  • 编译器织入, 这要求有特殊的Java编译器.
  • 类装载期织入, 这需要有特殊的类装载器.
  • 动态代理织入, 在运行期为目标类添加增强(Advice)生成子类的方式.

通知类型

  • 前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
  • 后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。
  • 异常通知(After throwing advice):在方法抛出异常退出时执行的通知。

AOP原理

上面说到了AOP可以在编译时候将代码织入到指定的方法或者属性上,或者在运行的时候动态的将代码切入到指定的方法或者属性中,这描述了AOP应该要做的事情,其实也基本算是它的原理了,AOP实现的关键就是创建AOP代理,代理有静态代理和动态代理之分,其中AspectJ为静态代理,Spring AOP是动态代理,这里把静态和运行时动态的分开说。

  • AspectJ(静态代理)
  • Spring AOP(动态代理)

AspectJ编译时增强(静态代理)

AspectJ编译时增强,既是静态代理增强,也就是会在编译阶段生成代理,将代码织入到Java的字节码中去。

Spring AOP的运行时增强(动态代理)

Spring AOP是基于代理机制的,并且Spring AOP使用的是动态代理增强,动态代理不会改变类的字节码,而是动态的生成代理对象。Spring AOP的动态代理机制有两种方式:JDK动态代理和CGLIB动态代理。

Spring有两种实现AOP的方式

  1. Java动态代理
  2. CGlib。默认使用动态代理

当目标对象没有实现接口时,就会使用后者。

JDK动态代理

JDK动态代理需要被代理的类必须实现一个接口,通过使用反射来接受被代理的类。

CGLIB动态代理

CGLIB动态代理可以不用需要被代理类必须实现接口,被代理类可以是一个类。

 

参考:

https://www.cnblogs.com/hongwz/p/5764917.html