Cglib动态代理实现
Cglib动态代理代码实现
Cglib是一个开源框架,可以在maven项目的pom.xml中引用,通过Cglib可以实现不依赖于接口的动态代理模式。同JDK动态代理实现模式对比,Cglib依赖类继承和重写,JDK依赖接口实现和方法实现。下面用Java实现Cglib动态代理:
1.定义一个不基于实现接口的类:1
2
3
4
5public class MovieStar extends Star{
public void movieShow(){
System.out.println("执行演员功能");
}
}
2.实现MethodIntercepter接口:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public class CglibProxyHandler implements MethodInterceptor {
Object target=null;
public CglibProxyHandler(Object target){
this.target=target;
}
public Object getInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
//第一个参数 代理对象,动态生成,通过getInstance方法获取
//第二个参数 委托类方法,实现的MovieStar类对象
//第三个参数 方法参数,传递给委托类对象方法的参数
//第四个参数 代理方法的MethodProxy对象,委托类每个方法都对应一个MethodProxy对象
//methodProxy.invokeSuper方法实际调用MethodProxy对象中的invokeSuper方法,MethodProxy对象内部定义了一个静态内部类,保存了动态生成的代理类对象和委托类对象引用类型为FastClass(提供通过索引的方式定位到具体方法)。通过调用代理类对象中的invoke方法,需要传人方法索引,代理对象和方法参数。调用CGLIB$movieShow$0方法执行super.movieShow()。
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("准备开始执行代理类方法");
methodProxy.invokeSuper(o,objects);
System.out.println("已经执行完代理类方法");
return null;
}
}
3.客户端调用动态生成代理类:1
2
3
4
5
6
7
8public class Client {
public static void main(String[] args){
MovieStar movieStar=new MovieStar();
CglibProxyHandler cglibProxyHandler=new CglibProxyHandler(movieStar);
MovieStar star=(MovieStar)cglibProxyHandler.getInstance();
star.movieShow();
}
}
4.输出结果:1
2
3准备开始执行代理类方法
执行演员功能
已经执行完代理类方法
Cglib动态代理源码阅读对比JDK动态代理
读源码相对还是比较抽象,笔者也主要阐述一些自己对Cglib动态代理源码的理解。其实无论是Cglib还是JDK动态代理实际上都是探讨如何设计这个动态生成的代理类,将所有的工作交给运行时过程去动态维护而不是人工维护。
Cglib动态代理与JDK动态代理基本区别
1.Cglib动态代理委托类不需要实现接口,扩展性更强,而JDK动态代理通过
1 | Proxy.newProxyInstance(mtarget.getClass().getClassLoader(),mtarget.getClass().getInterfaces(),this) |
的方式去反射出一个代理类就必然需要获取到委托类对象的接口信息。
2.Cglib动态代理不依赖于JDK的反射,而是定义了一个方法入口的索引,这样的实现方式较JDK动态代理的反射实现方式是高效的。
3.Cglib动态代理中生成的字节码更加复杂,生成的代理类是委托类的子类,且不能处理被final关键字修饰的方法。
Cglib动态代理源码实现
不多说,先上图:
动态生成的代理类实例
1 | import net.sf.cglib.core.Signature; |
MethodProxy对象
1 | public class MethodProxy { |
FastClass实现机制
1 | /*FastClass其实就是对Class对象进行特殊处理,提出下标概念index,通过索引保存方法的引用信息,将原先的反射调用,转化为方法的直接调用,从而体现所谓的fast,下面通过一个例子了解一下FastClass的实现机制。*/ |
总结
对于本篇Cglib动态代理源码的解读可能并没有很大的实际价值,笔者倒觉得这种实现方式源码逻辑封装得过于复杂。可以简单的理解Cglib动态生成的代理类是为每个委托类的方法维护了两个方法,一个是客户端调用入口方法,一个是通往其父委托类的入口,这样增大了字节码的复杂度,用空间换取了时间,实现了高效,同时不基于接口实现。
- **JDK只能代理实现了接口的类,Cglib