浅谈CglibJdk以及ProxyFactory实现动态代理上的区别
Posted 默辨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈CglibJdk以及ProxyFactory实现动态代理上的区别相关的知识,希望对你有一定的参考价值。
动态代理就是在不改变原代码逻辑的基础上,对代码功能进行增强。
一、Jdk动态代理
Jdk的动态代理是基于接口的,即如果想要对目标对象进行增强,目标对象一定要实现某一个接口,因为传入的参数就是接口。
在Spring与MyBatis的整合过程中,就是使用jdk的动态代理,对Mapper文件进行代理,最终成为Spring中的Bean对象。
1、新增一个UserService接口

2、新增一个接口的实现类UserrServiceImpl

3、编写Jdk动态代理测试类

测试结果:

二、Cglib动态代理
Cglib接触比较少,但他也是一种实现动态代理的方式,使用该方式进行功能增强的时候,被代理的对象不需要实现接口,可以简单的理解为要求更低。
1、对之前的UserServiceImpl类进行改造

2、编写对应的Cglib测试代码

测试结果:

补充:
3、对同一个类的不同方法使用不同的代理方法
对该cglib代理测试方法进行改造。使得我们在调用show方法时,触发对应的增强功能;使用test方法的时候,不进行任何的增强操作。
setCallbacks方法内编写方法的代理逻辑
setCallbackFilter方法内编写被代理对象的方法过滤逻辑

测试结果:

三、ProxyFactory动态代理
前面介绍了两种不同的实现动态代理的方式。在Spring的动态代理中,同样支持上面的两种不同形式的动态代理,Spring会根据代理对象的不同条件,选择使用不同的实现动态代理的方式。

试问,如果让你实现一个功能,如何让两个不同的操作,变得统一?
你可以试着想一想Spring是如何使用xml形式、@Bean形式、@Component形式定义Bean的。没错,就是定义一个中间态,即BeanDefinition。
Spring这里也有同样的设计,它将两个不同的对象操作集中到一个ProxyFactory对象上,最终使用ProxyFactory对象来执行对应的动态代理操作。
Spring中的AOP就是使用ProxyFactory来实现的,所以下面的测试代码,我也仿造AOP部分的代码进行测试
1、编写对应的Before方法

2、编写对应的After方法

3、编写对应的Throws方法

4、编写对应的测试方法
如果在advice中不添加MethodInterceptor对象,那么就会使用默认的逻辑,即仅完成show方法的调用。
即此处展示的代码MethodInterceptor部分的代码可以省略,然后将代理逻辑都封装到advice实现类中即可。

观察测试代码,我们可以发现,使用factory.getProxy()获取的结果再强转为UserService后是一个null,一个null依然能够调用show方法,由此可见此时是使用代理对象进行方法调用的,通过旁边的调试框我们也不难发现使用的是Cglib代理方法生成了代理对象。
即如果我们想要执行方法后的对象,只需要在return的时候,返回我们的proceed对象就好了。

5、高级版本,更细粒度的代理
通过观察addAdvice方法的底层我们可以发现,我们添加的addvice对象,最终都会封装为advisor对象

测试代码:
Advice + Pointcut = Advisor
Pointcut:何种条件才能满足切入点条件,即何种条件才进行Advice的代理逻辑
Advice:对应的代理逻辑
理解使用该种方式定义Advisor,对于Spring中AOP源码部分理解起着至关重要的作用!!!

测试结果:
MoBeforeAdvice是默认添加的代理逻辑,所以两个方法都会进行调用
MoAfterAdvice只有当调用的方法为test的时候才进行调用

四、Spring中AOP源代码分享
Spring的AOP就是通过ProxyFactory进行实现的,通过观察上面的内容我们不难发现,想要完成对一个方法的代理,大致需要以下一个步骤即可:
1. 找到符合当前Bean的所有的Advice
2. 将所有的Advice添加到ProxyFactory的对象中
3. 调用对应的方法
其实AOP就这么简单,详细的AOP源码分析可以参考:xxxx
此处仅展示部分源代码截图:
1、AOP方法的代理入口

2、找到当前Bean的所有Advice

3、找到符合当前Bean的所有的Advice

4、将所有的advisor对象添加ProxyFactory的对象中

5、获得对应的Advisor责任链并调用入口

6、最终的调用方法位置

以上是关于浅谈CglibJdk以及ProxyFactory实现动态代理上的区别的主要内容,如果未能解决你的问题,请参考以下文章
Spring读源码系列之AOP--04---proxyFactory创建代理对象
dubbo源码阅读-ProxyFactory之StubProxyFactoryWrapper本地存根
#yyds干货盘点# 老王读Spring AOP-4Spring AOP 与Spring IoC 结合的过程 && ProxyFactory 解析