JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
委托类:
package com.reflect.proxy;
public class GunDog1 {
public void info() {
System.out.println("我是一只美丽的猎狗");
}
public void run() {
System.out.println("我非常的奔跑迅速");
}
}
通用的方法:
package com.reflect.proxy;
public class DogUtil {
public void method1(){
System.out.println("=====模拟第1个通用方法======");
}
public void method2(){
System.out.println("=====模拟第2个通用方法======");
}
}
代理类“:
interceptor(Object obj,Method method,Object[] args ,MethodProxy proxy) 是CGLib定义的Interceptor接口的方法,它拦截所有目标类方法的调用 ,obj表示目标类的实例;method为目标类方法的反射对象;args为方法的动态入参;而proxy为代理类方法实例.
package com.reflect.proxy;
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 yulei
*
*/
public class GunDogCglib implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*/
public Object getInstance(Object target){
this.target=target;
Enhancer enhancer=new Enhancer();
//设置要创建子类的类
enhancer.setSuperclass(this.target.getClass());
//回调方法
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
DogUtil du=new DogUtil();
//执行DogUtil中的method1
du.method1();
Object result= methodProxy.invokeSuper(object, args);
//执行DogUtil中的Method2
du.method2();
return result;
}
}
测试类:
package com.reflect.proxy;
public class TestCglib {
/**
* @param args
*/
public static void main(String[] args) {
GunDogCglib dogCglib=new GunDogCglib();
GunDog1 gunDog1=(GunDog1) dogCglib.getInstance(new GunDog1());
gunDog1.run();
}
}
输出:
=====模拟第1个通用方法======
我非常的奔跑迅速
=====模拟第2个通用方法======
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理