AOP模块的实现

AOP是什么

要理解 AOP 是什么,请想象着你的面前有一条从左到右的线段,线段的最左端是代码执行起点,最右端则是执行终点。
现在代码执行到一半,也就是线段的中间时,那里藏着个人,他发现代码执行到他那里了,于是他就针对代码的执行做了一些记录,比如计算代码执行的速度和健壮度等资料。

Q:一般情况下,那个人是不会藏着那里的,为什么我们需要他那样藏起来呢?
A:因为我们不希望在代码不知情的情况下,做一些额外的动作。
有人又问了:要那个人藏在那里干嘛,直接在代码里写一些记录的模块不就行了?一般情况下我们是不需要他的,但是,如果有很多线端而我们不需要写多个记录模块呢?这时他就有用了,他可以同时观察多条线段,还能有选择地记录他想要的代码。

而所谓的 AOP,就是面向切面编程,在代码的中间弄一个切面,放入一个“他”,让他来观察,做一些额外的工作,比如做日志等,在许多条不交叉执行的代码中,只需要一个“他”,省时省力。

AOP 概念

advice通知

advice 就是上面所说的“额外工作”,advice 代表着当代码执行到某个方法时你想要做的额外工作,比如记录下该方法执行的次数?

pointcut切入点

pointcut 很容易理解,就是在代码执行过程中被切出的空位,在空位上可以执行你想要的额外工作。举个例子,代码执行过程中会执行4个方法,你希望在执行后3个方法时都记录下它们各自被执行多少次,那么,后三个方法的入口就是切入点:执行后3个方法之前先执行你的额外工作。

advisor 通知器

advisor 将 pointcut 和 advice 连接起来,当代码执行到切入点时,advisor使得代码跳到advice中去,执行完额外工作再跳回来。

target 目标

target就是上面所说的后三个方法,你定义的advice实际上增强了target。

AOP实现

AOP依赖了JDK的动态代理技术,给target生成一个代理对象,想要执行target时,并不是真正地执行target,而是执行代理对象的方法,由代理对象去调用target,由这里可以看出,target是完全不知道代理的存在的(这正是 AOP 的精髓,我们写的 AOP 模块并不影响实际业务的代码,而是悄悄地在幕后工作)

代理对象的简介

在 Spring 中,有两种生成代理对象的方法,一种是利用 JDK 的代理,另一种则是利用 GGLib。生成的代理对象中,包含了advice通知(也就是你想要的额外的工作),也包含了拦截器链和通知器。

生成代理对象时,需要指定target在何方,指定代理哪些方法,指定在target执行前代理对象需要执行的方法,只有这样,在执行 target 前,代理对象中的方法才会被调用,并先target一步执行额外的动作。

代理对象在执行额外的方法时,会进入“拦截链”去一个个对比哪个方法才是额外的方法(匹配的方式就是依据上面的通知器,通知器是用 IOC 容器的方式获得),遍历完拦截链后再执行target(使用反射的方式去执行target)。

拦截链

一般地,拦截链是一系列的拦截器,拦截器则是处在 pointcut 中。当代码跳入代理对象的方法体内后,后一个个地遍历切入点,如果符合,就根据advicor通知器,去唤醒并执行advice通知,直到所有的切入点均被遍历完。

结语

到此为止,AOP就可以正常地在业务代码不知情的情况下运转了。