摘要:本文次要讲了 Spring Aop 动静代理实现的两种形式。
1. Spring AOP
Spring 是一个轻型容器,Spring 整个系列的最最外围的概念当属 IoC、AOP。可见 AOP 是 Spring 框架中的外围之一,在利用中具备十分重要的作用,也是 Spring 其余组件的根底。AOP(Aspect Oriented Programming),即面向切面编程,能够说是 OOP(Object Oriented Programming,面向对象编程)的补充和欠缺。OOP 引入封装、继承、多态等概念来建设一种对象层次结构,用于模仿公共行为的一个汇合。不过 OOP 容许开发者定义纵向的关系,但并不适宜定义横向的关系,例如日志性能。
对于 AOP 的基础知识,并不是本文的重点,咱们次要来看下 AOP 的外围性能的底层实现机制:动静代理的实现原理。AOP 的拦挡性能是由 java 中的动静代理来实现的。在指标类的根底上减少切面逻辑,生成加强的指标类(该切面逻辑或者在指标类函数执行之前,或者指标类函数执行之后,或者在指标类函数抛出异样时候执行。不同的切入机会对应不同的 Interceptor 的品种,如 BeforeAdviseInterceptor,AfterAdviseInterceptor 以及 ThrowsAdviseInterceptor 等)。
那么动静代理是如何实现将切面逻辑(advise)织入到指标类办法中去的呢?上面咱们就来具体介绍并实现 AOP 中用到的两种动静代理。
AOP 的源码中用到了两种动静代理来实现拦挡切入性能:jdk 动静代理和 cglib 动静代理。两种办法同时存在,各有优劣。jdk 动静代理是由 java 外部的反射机制来实现的,cglib 动静代理底层则是借助 asm 来实现的。总的来说,反射机制在生成类的过程中比拟高效,而 asm 在生成类之后的相干执行过程中比拟高效(能够通过将 asm 生成的类进行缓存,这样解决 asm 生成类过程低效问题)。
上面咱们别离来示例实现这两种办法。
2. JDK 动静代理
2.1 定义接口与实现类
下面代码定义了一个被拦挡对象接口,即横切关注点。上面代码实现被拦挡对象接口。
2.2 JDK 动静代理类
上述代码实现了动静代理类 JDKProxy,实现 InvocationHandler 接口,并且实现接口中的 invoke 办法。当客户端调用代理对象的业务办法时,代理对象执行 invoke 办法,invoke 办法把调用委派给 targetObject,相当于调用指标对象的办法,在 invoke 办法委派前判断权限,实现办法的拦挡。
2.3 测试
后果如下:
3. CGLIB 字节码生成
3.1 要代理的类
CGLIB 既能够对接口的类生成代理,也能够针对类生成代理。示例中,实现对类的代理。
该类的实现和下面的接口实现一样,为了放弃对立。
3.2 CGLIB 动静代理类
上述实现了创立子类的办法与代理的办法。getProxy(SuperClass.class) 办法通过入参即父类的字节码,扩大父类的 class 来创立代理对象。intercept() 办法拦挡所有指标类办法的调用,obj 示意指标类的实例,method 为指标类办法的反射对象,args 为办法的动静入参,methodProxy 为代理类实例。method.invoke(targetObject, args) 通过代理类调用父类中的办法。
3.3 测试
后果如下:
4. 总结
本文次要讲了 Spring Aop 动静代理实现的两种形式,并别离介绍了其优缺点。jdk 动静代理的利用前提是指标类基于对立的接口。如果没有该前提,jdk 动静代理不能利用。由此能够看出,jdk 动静代理有肯定的局限性,cglib 这种第三方类库实现的动静代理利用更加宽泛,且在效率上更有劣势。
JDK 动静代理机制是委托机制,不须要以来第三方的库,只有要 JDK 环境就能够进行代理,动静实现接口类,在动静生成的实现类外面委托为 hanlder 去调用原始实现类办法;CGLib 必须依赖于 CGLib 的类库,应用的是继承机制,是被代理类和代理类继承的关系,所以代理类是能够赋值给被代理类的,如果被代理类有接口,那么代理类也能够赋值给接口。
参考
- jdk 动静代理代理与 cglib 代理原理探索
- AOP 的底层实现 -CGLIB 动静代理和 JDK 动静代理
本文分享自华为云社区《还不懂 Spring AOP?一文带你搞懂动静代理》,原文作者:aoho。
点击关注,第一工夫理解华为云陈腐技术~