再看java动态代理之Cglib动态代理,早期大家选择Cglib主要是因为Cglib底层采用ASM字节码生成框架,运行效率要比使用JDK原生代理高。
Cglib动态代理实现
//1.定义一个被代理类(cglib是生成被代理类的一个子类,不能直接用接口)
public class SayHi {
public void sayHi(String name){
System.out.println("hi: " + name);
}
}
//2..实现代理方法(实现MethodInterceptor接口),创建代理类
public class SayHiCglib implements MethodInterceptor{
private Object target;//业务类对象,供代理方法中进行真正的业务方法调用
//相当于JDK动态代理中的绑定,创建代理对象
public Object getInstance(Object target) {
this.target = target; //给业务对象赋值
Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
enhancer.setCallback(this);
// 创建动态代理类对象并返回
return enhancer.create();
}
// 实现回调方法,实现代理方法
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before method...");
proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
System.out.println("after method...");
return null;
}
}
//3.测试
public class CglibTest {
public static void main(String[] args) {
SayHi sayHi = new SayHi();
SayHiCglib cglib = new SayHiCglib();
SayHi sayHiProx = (SayHi) cglib.getInstance(sayHi);
sayHiProx.sayHi("z3");
}
}
可以看出来实现起来很简单,主要的是要学会代理这种思想,用这种方式去解决工作中具体遇到的问题。
Cglib与JDK动态代理比较
JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;
CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码。
JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法。
注意事项
使用Cglib动态代理除了要引用cglib本身的jar包还需要引入asm的jar包,因为Cglib底层采用ASM字节码生成框架。
Cglib采用的是继承,所以不能使用final对被代理类进行修饰。