JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
下面是使用cglib实现动态代理的一个例子。需要导入两个jar文件。asm.jar – Cglib的底层实现。【cglib包的底层是使用字节码处理框架ASM来转换字节码并生成新的类,所以cglib包要依赖于asm包】。 cglib.jar - Cglib的核心jar包。
被代理的类
package com.bobohe.cglibproxy;
/**
* 被代理的类
* @author Administrator
*
*/
public class CglibProxyTest {
public void test(){
System.out.println("do cglib proxy test!");
}
}
cglib动态代理类
package com.bobohe.cglibproxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 使用cglib动态代理
* @author lvzb.software@qq.com
*
*/
public class CglibDynamicProxy implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
* @param target 被代理的对象
* @return
*/
public Object getProxyInstance(Object target){
this.target = target;
// 声明增强类实例
Enhancer enhancer = new Enhancer();
// 设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
enhancer.setSuperclass(this.target.getClass());
// 设置要代理的拦截器,回调函数,即一个方法拦截 new MethodInterceptor()
enhancer.setCallback(this);
// 创建代理对象 实例
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 在代理真实对象操作前 我们可以添加一些自己的操作
System.out.println("前置代理,增强处理");
proxy.invokeSuper(obj, args);
// 在代理真实对象操作后 我们也可以添加一些自己的操作
System.out.println("后置代理,增强处理");
return null;
}
}
客户端类
package com.bobohe.cglibproxy;
public class CglibClient {
public static void main(String[] args) {
CglibDynamicProxy cglib = new CglibDynamicProxy();
CglibProxyTest proxyInstance = (CglibProxyTest) cglib.getProxyInstance(new CglibProxyTest());
proxyInstance.test();
}
}
总结:CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理