AOP
面向切面编程实际上做一个代码增强, AOP像OOP一样是一种编程范式。 我们不光可以对方法进行增强,
也可以对构造函数,字段进行增强。(例如使用aspect J). 这里我只关注方法执行过程前后的织入,也就是运行期进行织入。
根据织入的时期,可以分为以下几个时期
- 编译前
- 编译后
- 装载后
- 运行期
比较有名的Spring AOP 是在运行期实现代码增强。
Spring AOP 基于以下两种实现,当代理对象实现某个接口时候会优先采用jdk动态代理, 如果代理对象无任何接口实现则基于CGlib 实现动态代理
动态代理
基于JDK的动态代理
- 定义一个回调类定义拦截后的方法回调对象(implement InvocationHandler)
- 使用Proxy.newProxyInstance() 生成代理对象。该方法有三个参数, 第一个是所属的classloader.
第二个是该代理对象实现的接口的数组, 第三个是1定义的回调对象
1 | class AppClientProxyHandler implements InvocationHandler { |
AppClientProxyHandler 动态代理 AppClient 接口,对于applient 接口的调用都会被代理
增强的代码就是:
1 | RpcConnection<D4cRpcClient, CommD4cService.Client> conn = pool.getAvailableConnnection(); |
增强目的:重复使用pool中“可贵“资源RpcConnection
基于CGLib方案
对于每个DAO调用之前做方法拦截回调, 检查版本是否符合预期,不符合预期不加载, 类似于权限检查。
事实上对于sesion 的权限检查也应该基于AOP去做。 对于版本更新,则在sava成功之后去做。
- 定义方法调用前回调对象
在dao真正调用前进行”版本检测”
1 | public class VersionCheckHandler implements MethodInterceptor { |
- 定义方法调用后回调对象
在dao完成写操作后,进行“写版本”操作
1 | public class VersionSaveHandler implements MethodInterceptor { |
- 对于原来的DAO进行”代理”增强, 生成新的DAO 对象:
1 | public class ProxyFactory { |
AOP编程思想
OOP的有效补充(引用于知乎)
- 面向对象(OOP)引入了继承、多态、封装,将系统的业务功能按照模块划分,每个模块用一个或多个类来表示。
- 而对于一些系统功能,无法使用OOP的思想来实现它们。这些系统功能往往穿插在业务功能的各处,和业务代码耦合在一起;而且系统功能往往会被重复使用,这就导致了模块不利于复用,这就是使用OOP实现系统功能的弊端。
- AOP即为面向切面编程,它把系统需求按照功能分门归类,把它们封装在一个个切面中,然后再指定这些系统功能往业务功能中织入的规则。最后由第三方机构根据你指定的织入规则,将系统功能整合到业务功能中。