使用CGLib实现动态代理

一、背景
    在上一篇博客中(java动态代理:http://blog.csdn.net/wenhuayuzhihui/article/details/51700670)提到,java的动态代理是必须基于接口的,而在编程中,使用到的外部类并不是基于接口编程的比比皆是,这有如何实现动态代理?使用可以基于类实现动态代理的CGLib!

二、简介
    CGLib(Code Generation Library)是一个强大、高性能的Code生成类库,它可以在程序运行期间动态扩展类或接口;它的底层是使用java字节码操作框架ASM实现;

三、使用
    CGLib核心类:

1、net.sf.cglib.proxy.Enhancer:主要增强类,通过字节码技术动态创建委托类的子类实例;

2、net.sf.cglib.proxy.MethodInterceptor:常用的方法拦截器接口,需要实现intercept方法,实现具体拦截处理;

public java.lang.Object intercept(java.lang.Object obj,
                                  java.lang.reflect.Method method,
                                  java.lang.Object[] args,
                                  MethodProxy proxy)
                           throws java.lang.Throwable
obj:动态生成的代理对象
method : 实际调用的方法
args:调用方法入参
proxy:
net.sf.cglib.proxy.MethodProxy:java Method类的代理类,可以实现委托类对象的方法的调用;常用方法:methodProxy.invokeSuper(proxy, args);在拦截方法内可以调用多次

我们继续以java动态代理实例的需求演示CGLib动态代理(调用外部类方法是,打印入参,完成后,打印结果),假设外部类没有基于接口编程,我们无法再使用java的动态代理实现这个需求,只能使用CGLib实现:
/**
 * 简单的外部类
 * @author hwz
 *
 */
public class OtherOuterClass {

    /**
     * 字符串翻转
     * @param str
     * @return
     */
    public String methodOne(String str) {
        return new StringBuilder(str).reverse().toString();
    }

    /**
     * 两个整数乘积
     * @param a
     * @param b
     * @return
     */
    public int methodSecond(int a, int b) {
        return a*b;
    }
}
/**
 * 代理方法拦截器
 * @author hwz
 *
 */
public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        //打印入参日志
        StringBuilder builder = new StringBuilder();
        if (args != null) {
            for (int i=0; i 
   
/**
 * 测试类
 * @author hwz
 *
 */
public class CglibProxyTest {

    public static void main(String[] args) {

        CglibProxy cglibProxy = new CglibProxy();
        OtherOuterClass proxyObj = (OtherOuterClass) cglibProxy.getProxy(OtherOuterClass.class);

        proxyObj.methodOne("abcdef");
        proxyObj.methodSecond(2, 4);
    }
}
在spring的AOP中,就是使用到java的动态代理和CGLib,默认情况下,基于接口的切面是使用java动态代理;
有比较表明CGLib的性能高于java本身的动态代理,后续我们再比较分析;




你可能感兴趣的:(Java)