Cglib基于字节码生成功能(类似于jdk proxy),提供了简单但是强大的动态代理的能力.代码样例基于cglib-2.1.3和asm-1.5.3:
1. Proxy动态代理:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
TestObject orignal = new TestObject();
//基于接口代理
//底层仍基于Enhancer类
TestInterface proxy = (TestInterface)Proxy.newProxyInstance(classLoader, new Class[]{TestInterface.class}, new TestInvocationHandler(orignal));
proxy.testPrint("I am proxy");
static class TestInvocationHandler implements InvocationHandler{
private TestInterface orignal;//被代理类对象,
TestInvocationHandler(TestInterface orignal){
this.orignal = orignal;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//around
System.out.println("before invoked ");
Object result = method.invoke(orignal, args);
System.out.println("after invoked");
return result;
}
}
/**
* 接口,需要为public
*
*/
public static interface TestInterface{
public void testPrint(String message);
}
static class TestObject implements TestInterface{
public void testPrint(String message) {
System.out.println(message);
}
}
Cglib的proxy几乎和jdk proxy一样,无论是在api还是设计思路上..二者没有太多的差异性.对于cglib-proxy,底层仍然基于Enhance类做辅助操作(更底层仍然是字节码Generator),仍然是生成Proxy类($Proxy),代理的方式仍然是基于"接口列表"和InvocationHandler.
2. Enhancer动态代理与方法拦截:
//使用TestObject类的默认构造函数,创建代理类实例,此代理类支持"方法拦截"
//Enhance不仅支持基于接口列表的方式创建代理类,还支持使用"基类"的方式创建.
Callback interceptor = new TestMethodInterceptor();
//底层仍基于Generator来创建代理类(class)且被缓存
TestObject proxy = (TestObject)Enhancer.create(TestObject.class, interceptor);
proxy.testMethod();
Callback interceptor = new TestMethodInterceptor();
//指定构造函数,创建代理类实例
Enhancer enhancer = new Enhancer();
enhancer.setCallback(interceptor);
enhancer.setSuperclass(TestObject.class);
//使用构造函数TestObject(String name)
TestObject proxy = (TestObject)enhancer.create(new Class[]{String.class}, new Object[]{"zhangsan"});
proxy.testMethod();
static class TestMethodInterceptor implements MethodInterceptor{
/**
* @param obj 代理对象
* @param method 调用的方法,基于jdk reflect,此方法不能直接在当前对象中使用,只能使用在其他实例上,否则将无限循环触发"拦截器"
* @param proxy 经过封装的代理类的方法
*/
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("here");
//执行当前代理对象的方法
proxy.invokeSuper(obj, args);
TestObject other = new TestObject("lisi");
//如下两个方法,不能在当前代理对象中使用.
method.invoke(other, args);
proxy.invoke(other, args);
return null;
}
}
Enhancer是cglib中用于创建动态代理类的辅助类,它和Proxy类比较起来,不仅能够支持"接口列表"代理,还能支持基于"基类"的代理:
enhancer.setSuperclass(TestObject.class);
Enhancer主要是用来创建"AOP"外观的代理类,它支持了方法拦截特性.