一文带你搞懂从动态代理实现到Spring AOP

摘要:本文主要讲了Spring Aop动态代理实现的两种方式。

1. Spring AOP

Spring是一个轻型容器,Spring整个系列的最最核心的概念当属IoC、AOP。可见AOP是Spring框架中的核心之一,在应用中具备很是重要的做用,也是Spring其余组件的基础。AOP(Aspect Oriented Programming),即面向切面编程,能够说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来创建一种对象层次结构,用于模拟公共行为的一个集合。不过OOP容许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。java

关于AOP的基础知识,并非本文的重点,咱们主要来看下AOP的核心功能的底层实现机制:动态代理的实现原理。AOP的拦截功能是由java中的动态代理来实现的。在目标类的基础上增长切面逻辑,生成加强的目标类(该切面逻辑或者在目标类函数执行以前,或者目标类函数执行以后,或者在目标类函数抛出异常时候执行。不一样的切入时机对应不一样的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。编程

那么动态代理是如何实现将切面逻辑(advise)织入到目标类方法中去的呢?下面咱们就来详细介绍并实现AOP中用到的两种动态代理。segmentfault

AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来讲,反射机制在生成类的过程当中比较高效,而asm在生成类以后的相关执行过程当中比较高效(能够经过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。缓存

下面咱们分别来示例实现这两种方法。框架

2. JDK动态代理

2.1 定义接口与实现类

image

上面代码定义了一个被拦截对象接口,即横切关注点。下面代码实现被拦截对象接口。函数

image

2.2 JDK动态代理类

image

上述代码实现了动态代理类JDKProxy,实现InvocationHandler接口,而且实现接口中的invoke方法。当客户端调用代理对象的业务方法时,代理对象执行invoke方法,invoke方法把调用委派给targetObject,至关于调用目标对象的方法,在invoke方法委派前判断权限,实现方法的拦截。测试

2.3 测试

image

结果以下:spa

image

3. CGLIB字节码生成

3.1 要代理的类

CGLIB既能够对接口的类生成代理,也能够针对类生成代理。示例中,实现对类的代理。.net

image

该类的实现和上面的接口实现同样,为了保持统一。3d

3.2 CGLIB动态代理类

image

上述实现了建立子类的方法与代理的方法。getProxy(SuperClass.class)方法经过入参即父类的字节码,扩展父类的class来建立代理对象。intercept()方法拦截全部目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,methodProxy为代理类实例。method.invoke(targetObject, args)经过代理类调用父类中的方法。

3.3 测试

image

结果以下:

image

4. 总结

本文主要讲了Spring Aop动态代理实现的两种方式,并分别介绍了其优缺点。jdk动态代理的应用前提是目标类基于统一的接口。若是没有该前提,jdk动态代理不能应用。由此能够看出,jdk动态代理有必定的局限性,cglib这种第三方类库实现的动态代理应用更加普遍,且在效率上更有优点。

JDK动态代理机制是委托机制,不须要以来第三方的库,只要要JDK环境就能够进行代理,动态实现接口类,在动态生成的实现类里面委托为hanlder去调用原始实现类方法;CGLib 必须依赖于CGLib的类库,使用的是继承机制,是被代理类和代理类继承的关系,因此代理类是能够赋值给被代理类的,若是被代理类有接口,那么代理类也能够赋值给接口。

参考

  1. jdk动态代理代理与cglib代理原理探究
  2. AOP的底层实现-CGLIB动态代理和JDK动态代理

本文分享自华为云社区《还不懂Spring AOP?一文带你搞懂动态代理》,原文做者:aoho 。

点击关注,第一时间了解华为云新鲜技术~