代理模式(七)

       CGLIB(Code Generation Library)是一个开源项目,是一个强大的、高性能、高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口,hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。

       CGLIB代理实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的Java字节码编辑类库)操作字节码实现的,性能比JDK强。主要使用于改造遗留系统,这些系统一般不会继承特定的接口。

JDK动态代理与CGLIB动态代理区别

       (1)JDK 动态代理

       1、只能代理实现了接口的类;
       2、没有实现接口的类不能实现JDK的动态代理。

       (2)CGLIB动态代理

       1、针对类来实现代理的;
       2、对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

代码实现

       cglib动态代理实现需要导入相关包,此处导入的为cglib-nodep-2.2.jar,然后需要创建事务处理器类,并实现MethodInterceptor接口,事务处理器类CglibProxy源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.cjlibproxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

//实现MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {

private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}

/**
* 该方法用于拦截所有目标类方法的调用
* obj 目标类的实例
* m 目标方法的反射对象
* args 方法的参数
* proxy 代理类的实例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args,
MethodProxy proxy) throws Throwable {
//代理的业务逻辑
System.out.println("代理:开车");

//代理类调用父类的方法
proxy.invokeSuper(obj, args);

//代理的业务逻辑
System.out.println("代理:到了");
return null;
}

}

       有一个火车类,并没有实现接口:

1
2
3
4
5
6
7
8
package com.cjlibproxy;

public class Train {
public void move(){
System.out.println("火车行驶中");
}

}

       测试类:

1
2
3
4
5
6
7
8
9
10
package com.cjlibproxy;

public class Test {

public static void main(String[]args){
CglibProxy proxy = new CglibProxy();
Train t = (Train) proxy.getProxy(Train.class);
t.move();
}
}

       测试结果:

1
2
3
代理:开车
火车行驶中
代理:到了

       代码详见 PatternTest

参考资料:
王英豪 与接口相关的设计模式(2):代理模式、标识类型模式及常量接口模式
David 模式的秘密——代理模式

Fork me on GitHub