java 动态代理的两种实现方式

最近又回顾了一下动态代理,发现可以使用Cglib实现,所以做一次总结。

两种方式的优缺点是什么?实现的区别是什么?

 

本来我打算用半天时间完成这篇文章,所以在动手实现之前回顾了一下:

java 动态代理实现aop

结果我发现:我完全看不懂自己在写什么…所以我花了很长时间把原来的代码实现了一遍,把文章重构了一遍。

通过这件事我得到了一个教训:写文章的时候不要偷懒,要把实现过程写详细,把实现思路写清楚。

一、jdk动态代理

(1)jdk动态代理的实现

1.写一个接口类

TestInterface.java

2.写一个实现类实现接口

ImplementClass.java

3.写一个代理处理类

ProxyHandler.java

4.写一个工厂类

Factory.java

5.获取代理对象并且调用方法

Main.java

返回结果:

成功实现动态代理功能。

(2)jdk动态代理存在的问题

每次实现动态代理,我们总要遵循上面的流程:

先写接口,再写实现类,然后写代理处理类,接着写工厂类(或者直接调用,忽略工厂类),最后获取代理对象并且调用方法。

在整个流程中,特别需要留意newProxyInstance方法。在调用newProxyInstance方法时(即获取代理对象),必须要有interfaces参数(即被代理类必须实现某个接口)。

简单看一看方法的源码:

可以发现此方法是通过反射实现的,interfaces参数参与了整个对象的获取过程。在这里不做详细解读。

综上所述,如果某被代理类想实现动态代理,那么这个被代理类必须实现某个接口。

反过来想,我们也可以得出这样的结论:没有实现接口的类,无法实现动态代理。

这就是jdk动态代理的缺陷。

二、Cglib动态代理

(1)Cglib动态代理的实现

1.引入依赖

cglib是一个动态代理框架,底层基于ASM实现(底层使用ASM在内存中动态的生成被代理类的子类,即使代理类没有实现任何接口也可以实现动态代理功能),所以要同时引入多个依赖。

2.写一个被代理类

直接用上文的实现类,但是这次没必要实现接口(就算实现了也没关系)。

ImplementClass.java

3.写一个代理处理类

CglibProxyHandler.java

4.写一个工厂类

CglibFactory.java

在这里,获取代理对象的方法发生了变化。不再需要传入接口参数,但是依然需要用到被代理类的class和代理处理类的对象。

5.获取代理对象,并且调用方法

CglibMain.java

(2)Cglib动态代理存在的问题

Cglib原理是针对被代理类生成一个子类,覆盖其中的所有方法。

既然需要生成目标类的子类,那么子类肯定要继承被代理类,所以目标类和方法不能声明为final类型。

我看网上比较Cglib动态代理和JDK动态代理,结论为:“Cglib简单易用,而且Cglib动态代理运行速度远快于JDK动态代理”。

简单易用我倒是同意(实现流程比较好理解),但是我难以理解为什么Cglib运行速度更快。如果使用Cglib动态代理,不仅需要引入Cglib框架,还需要引入ASM框架,这两个框架进行的一系列处理居然可以比原生java的动态代理要快,有点出乎我所料。

个人猜测(没有看源码),Cglib动态代理不需要对被代理类的接口进行处理,只需要实现子类的继承,所以速度更快。

三、总结

又学会了一种新姿势,感觉不错。以后可以多多尝试使用Cglib动态代理。

发表评论

电子邮件地址不会被公开。 必填项已用*标注