什么是AOP
全称是Aspect Oriented Program 意为:面向切面编程。它是Spring框架中的一个非常重要内容,它允许我们通过预编译的方式和运行期间动态代理实现在不修改源代码的情况下给程序动态统一添加某种特定功能。什么意思呢?请接着往下看。
与OOP(面向对象)的联系和区别
要想深刻理解AOP,首先得知道它是怎么来的,为什么会有这个概念。
联系
先说结论,AOP其实就是OOP(面向对象)的延续。
我们回顾一下,OOP的三大特性是继承、多态和封装。其中封装要求将功能分散到不同的对象中去,通过对象来管理代码,这是一种职责分配模式。这样做的好处是降低了代码的复杂程度,使类可重用。但是在分散代码的同时,也产生了大量的重复代码。
例如,假设有两个类,都需要在每个方法中做日志。那么根据面向对象的思想,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
看到这,可能有会人说,可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。不错,这的确解决了代码复用的问题。
但与此同时又产生了新的问题,如果我们这样做,那么这两个类跟上面提到的独立的类就有耦合了,它的改变会影响这两个类。
那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这就引出了文章的主角——AOP。
这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面。
AOP是OOP的补充。OOP从横向上区分出一个个的类来,而AOP则从纵向上在对象中加入特定的代码。
区别
AOP、OOP是面向不同领域的两种设计思想。
OOP针对业务处理过程的实体及其属性和行为进行抽象封装,这是为了清晰地划分职责,获得便于管理和维护的单元模块。而AOP则是针对业务处理过程中的切面进行提取,它面向的是处理过程中的某个步骤或阶段,达到业务处理过程中各部分之间低耦合的效果。
我们再举例说明一下。
首先,在面向切面的编程思想中,我们可以把功能分为核心业务和周边功能(周边功能在AOP中,我们将其视为切面)
核心业务,比如登陆、注册,等需要访问数据库的方法;周边功能,比如性能统计,日志分析,事务管理等等。
以事务管理为例,这可能是很多核心业务都需要的功能,而对于一个优秀的开发人员,是很难忍受如此多的冗余代码的。所以,为了消除冗余,提高代码的质量,我们可以分别开发核心业务和周边功能,再把切面和核心业务功能 "编织" 在一起。
AOP中的核心概念
上文中提到了AOP中的一些概念,这里先简单讲述一下。
(可结合上图理解)
- Aspect(切面)
就是一个普通类或者被@Aspect注解修饰的类,只不过Spring赋予了它一些特定的作用(对其他的方法或者类做增强)
切面主要由切入点和通知组成
- Join point (连接点)
要被增强的程序中的某个位置, 如方法的调用或特定的异常被抛出,有点类似debug时我们手动设置的断点(若想进一步了解怎么实现断点,可以用Javap反编译字节码文件,一看便知)。
在Spring AOP中,连接点一般代表一个方法的执行( 换句话说,Spring AOP主要是对方法的增强)
- Advice(通知)
就是对某个具体的连接点增强的代码
在方法执行的什么时候(方法执行前/方法执行后/方法执行前后)做什么(增强的功能)
Spring AOP中有五种通知类型
通知类型 | 说明 |
---|---|
Before advice 前置通知 | 在目标方法执行之前执行的通知方法 |
After returning advice 返回后通知 | 在目标方法返回数据后执行( 正常执行完毕之后) |
After throwing advice 异常通知 | 在目标方法抛异常后执行 |
After (finally) advice 后置通知 | 无论目标方法正常运行完还是抛异常,都会执行的通知 |
Around advice | 环绕通知,能够一次性实现上面4种通知 |
Spring AOP框架以拦截器来实现通知,并维护一个以连接点为中心的拦截器链,这里不过多讲述。
- Pointcut(切入点)
就是用来匹配连接点的,主要通过切点表达式来匹配,表示在哪些类,哪些方法上切入
Spring使用AspectJ 切入点语法。所有的方法都可以认为是连接点,但是我们并不希望在所有的方法上都添加通知,而切入点的作用就是指定一种规则,给满足规则的连接点添加通知。
举一个例子:
execution(* com.juejin.service..*.*(..))
依次解释涉及到的通配符(从左到右):
*
:这个位置表示匹配的目标方法的返回值必须是什么, *
代表无所谓目标方法返回值是什么 ..
:这个表示匹配的包路径, ..
代表无所谓目标方法在多少层子包里面
*
:这个表示匹配的目标方法所在类的名字叫什么, *
代表无所谓类名
*
:这个表示目标方法的名字叫什么,*
代表匹配所有方法 ..
:这个表示目标方法的参数列表中的参数类型和个数, ..
代表无论方法有多少个参数和类型
- Target object(目标对象)
目标对象,包含即将要被增强的方法的对象,即包含主业务逻辑的类对象。一个目标对象可以被多个切面通知。
- AOP proxy(代理对象)
Spring AOP中,是被增强之后的方法所在的对象
- Weaving(织入)
就是将Advice( 通知 )加入到Target Object(目标对象)中的Join Point(连接点)上,生成AOP Proxy(代理对象)的过程。
织入可以在编译时,类加载时和运行时完成。在编译时进行织入就是静态代理,而在运行时进行织入则是动态代理。
AOP 的作用
用两个字就可以概括AOP的作用——增强。
展开说也不复杂,AOP能将那些与业务无关,但为业务模块所共同调用的功能(例如事务处理、日志管理、权限控制等)封装隔离起来,使得业务模块之间的耦合度降低,提高程序的可重用性和开发的效率,减少系统的重复代码,提高代码的灵活性和可扩展性。
END
希望各位掘友看完文章后有所收获,本人水平有限,难免有遗漏或出错的地方,恳请大佬多多指教!