使用动态代理实现AOP面向切面编程
一、概述
Aspect Oriented Programming(AOP),面向切面编程。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
二、案例
以上是用专业的语言的说法,我说了可能跟没说一样,你还是不懂。下面我举三个例子,你可能就懂了。我们先举个简单的例子,记录日志这种操作在开发中是经常使用的,我们通常在执行某个方法的前后加入输出日志的操作。那么问题来了,我们写了N多个方法,是不是要把记录日志的代码写个N遍呢?这显然是可以的,但是你肯定会有种想砸电脑的冲动。再比如,你要做一个网盘的项目,可能会有无数个地方让你上传文件。上传文件会经过一套你们公司专有的流程,比如检测文件的MD5值,并记录下来,以便于以后的秒传,或者是对一些偏黄色的视频文件进行识别。这些业务可能会在未来的某个时间点发生变动,这样你是不是得在所有上传文件的地方都要改。如果还不形象,我们可以举个生活中的例子。你有没有吃过披萨,披萨被切成很多小块,可以理解为我们有很多模块用到了上传文件。但我们要在其中加入培根或火腿片,我们可以横着来一刀,这个要加入培根和火腿片的这种业务就称之为aspect(切面)。我们可以决定哪些模块的上传文件功能需要加入这组特定业务逻辑,并非所有模块都要去加入培根或火腿片,也可以只给某人吃的那块加的。而我们具体要加入培根或火腿片的那个地方就是一个jointpoint(连接点),连接点是个静态的概念,指一个地方。而pointcut(切点),我也理解为切入点,就是要在连接点加入某些特定的操作,这里包含了业务逻辑,即考虑如何加入advice,这个概念我们后面会讲。在这个切点里面加入怎样的业务逻辑也完全取决于我们,到底是加培根还是火腿片,这个就是advice(处理逻辑)角色。
三、解决方案
要解决这样的问题,我们引入了AOP。我们可以通过AOP技术,在方法的前后加上某些特定的操作。注意了,AOP只是一种设计思想,并非一种代码写法。我们下面就要讲讲如何利用Java的动态代理机制来完成这一功能了。我们先简单回顾一下动态代理的知识。动态代理,简单的说,就是要实现java.lang.reflect.InvocationHandler接口。动态代理只能够代理接口。我们都知道,接口要被实例化,需要重写接口上所有的方法。但是,问题来了,你在做框架的时候,并不能确定具体的业务是怎么处理的,也就是回调接口中的代码是不可预知的。你new一个空的接口,有用吗?然而并没有什么卵用吧。那么,这个回调接口里面的代码,我们要怎么获取呢?我们可以用注解来配置。带有我们想要的注解的方法就是我们的真实回调的方法。在注解中,也可以提供大量我们需要的信息。在使用动态代理后,我们回调的方法就是我们的代理方法,即代理某些特定注解的方法。
四、项目实践
我写了一个最简单的实现的代码,你们也可以让advice处理逻辑这块很复杂,流程完全由你来控制。示例代码地址 https://github.com/JackWHLiu/jackknife/tree/master/jackknife-aop,下面就动手写一个简单的日志输出的AOP功能吧,相信你可以的。
五、支持一下作者
Github: https://github.com/JackWHLiu/jackknife
jackknife官网: https://jackwhliu.cn