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"外观的代理类,它支持了方法拦截特性.