一、前言
在前一篇《设计模式之代理模式(一)》中,我们了解到了什么是代理,以及代理的三个特点或必要条件:
- 必须包含两个角色:执行者和被代理人
- 被代理人中的任务必须执行
- 执行者中需要引用被代理人的资料信息即被代理人的引用。
同时,我们也使用了JDK自带的代理来实现了一个小Demo。不过由于代理最底层是一个字节码重组的过程,而且JDK的代理要求我们必须首先定义一个接口,还有就是性能上的局限性等,我们需要寻找更好的一种方式。
目前主流的还是基于第三方库cglib,所以需要我们在项目中引入第三方依赖cglib:cglib:版本。
二、CGLib
2.1 介绍
cglib是一个强大的,高性能和高质量的代码生成库。它用于在运行时扩展Java类【即继承父类】和实现接口。同时他也是免费的开源库。
2.2 分析
与JDK代理中定义接口不同,CGLib只需要定义一个代理类,CGLib内部会自动生成一个他的子类,且子类会重写该代理类中的非 final 方法。
2.3 应用
目前使用最广的 Spring AOP 中的代理就是基于 CGLib。
2.4 结构图
三、代码实践
3.1 创建代理类
根据上面的介绍,我们直接创建一个代理类,并实现其需要做的工作:
public class Developer {
public void helloWorld() {
System.out.println("开发人员写了一段 Hello World 的代码...");
}
}
3.2 创建执行者
// 这里有个拦截器的概念
public class DeveloperProxy implements MethodInterceptor {
public Object getInstance(Class superClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(superClass);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 这里需要注意,需要调用代理的父类方法
methodProxy.invokeSuper(obj, args);
return null;
}
}
3.3 测试
public class DeveloperProxyMain {
public static void main(String[] args) {
Developer developer = (Developer) new DeveloperProxy().getInstance(Developer.class);
System.out.println("代理类型:" + developer.getClass().getName());
developer.helloWorld();
}
}
观察结果:代理类型:com.hz.design.mode.proxy.cglib.Developer$$EnhancerByCGLIB$$a07de3f5
我们可以看到真正执行 helloWorld 方法的对象类型为 Developer$$EnhancerByCGLIB$$a07de3f5。
同样的,参考上一篇,我们可以将其输出到磁盘,并反编译查看生成的子类信息。