一、概述
上一节介绍了JDK动态代理,下面说一下使用CGLib实现动态代理。Cglib是一个强大的,高性能的Code生成类库,它可以在运行期间扩展Java类和实现Java接口,它封装了Asm,所以使用Cglib前需要引入Asm的jar。
JDK实现动态代理需要实现类通过接口定义业务方法,被代理的类必须实现接口;使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率更高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,由于是继承,因此使用CGLIB代理的类不能是final类。
二、代码实现
下面是CGLib实现动态代理的代码实现:
被代理类:
package static_proxy_package;
/**
* 委托类,真正要送礼物的人,实现了接口
* @author lsh
*
*/
public class RealSubject {
public void giveGift(String name) {
System.out.println(name + "送给了您一份礼物");
}
}
CGLib动态代理:
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibDynamicProxy implements MethodInterceptor {
public static CGLibDynamicProxy instance= new CGLibDynamicProxy();
public CGLibDynamicProxy(){ }
public static CGLibDynamicProxy getInstance(){
return instance;
}
//创建代理类
@SuppressWarnings("unchecked")
public <T>T getProxy(Class<T> cls){
return (T)Enhancer.create(cls,this);
}
@Override
public Object intercept(Object target,Method method, Object[] args,MethodProxy proxy)throws Throwable{
Object sub= null;
System.out.println("送礼物之前");
Object result =proxy.invokeSuper(target,args);
System.out.println("送礼物之后");
return result;
}
}
客户端:
public class Client {
public static void mian(String[] args){
RealSubject realSubject=CGLibDynamicProxy.getInstance().getProxy(RealSubject.class);
realSubject.giveGift("huazi");
}
}
三、浅析:
1、 CGLib实现动态代理的过程:
(1) Enhancer现将被代理类设置成父类,然后设置拦截器类,最后执行性enhancer.create()动态生成一个代理类;
(2) 回调MethodInterceptor接口的拦截方法intercept来实现代理逻辑,其中调用代理类实例上的proxy方法的父类方法proxy.invokeSuper(obj,arg).
2、解析intercept(Object obj, Method method,Object[] args,MethodProxy proxy)的参数:
(1) Object为由CGLib动态生成的代理类的实例;
(2) Method为调用被代理方法的引用
(3) Object[]为被调用代理方法的参数列表
(4) MethodProxy为生成的代理类对方法的代理引用。
四、区别:
注:红色字代表CGLib动态代理,黑色字代表JDK动态代理