A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© shi0000 中级黑马   /  2014-5-2 19:06  /  860 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

了解了张老师的JD代理,就不可缺少的认识CGLIB代理。以下是引自百度知道。

使用CGLIB动态代理
    Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类。使用CGLIB即使被代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
使用CGLIB需要导入以下两个jar文件:
    asm.jar – CGLIB的底层实现。
    cglib.jar – CGLIB的核心jar包。
CGLIB的核心类:
    net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:
    Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。

java代码:
1、使用CGLIB的代理:
以下测试代理一个没有实现任何接口的Person类:
    @Test
    public void testProxy1() throws Exception {
       final Person p1 = new Person();             //Person类没有实现任何接口
       Enhancer en = new Enhancer();               //声明增加类实例
       en.setSuperclass(Person.class);             //设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
       en.setCallback(new MethodInterceptor() {    //设置回调函数,即一个方法拦截
           public Object intercept(Object target, Method method,
                  Object[] args, MethodProxy proxy) throws Throwable {
              Object o = method.invoke(p1,args);    //注意参数p1,仍然为外部声明的源对象,且Method为JDK的Method反射
              System.err.println("After...");
              return o;
           }
       });
       Person p = (Person) en.create();             //通过create方法返回Person类的代理
       System.err.println(p.getClass());//被代理的对象
       p.sayHi("Hello");
    }
2、以下测试代理一个拥有接口的类:
IAnimal是接口,Dog是实现类,具体代码如下:
    @Test
    public void testProxy2() throws Exception {
       final Dog dog = new Dog();             //声明被代理对象
       Enhancer en = new Enhancer();          //声明CGLIB增强类
       en.setSuperclass(IAnimal.class);       //设置接口类,也可以设置成dog实现类,会影响create返回的对象
       en.setCallback(new MethodInterceptor() {
           public Object intercept(Object target, Method method,
                  Object[] args, MethodProxy proxy) throws Throwable {
              System.err.println("Before...");
              Object o = method.invoke(dog, args);
              System.err.println("After...");
              return o;
           }
       });
       //Dog dog2 = (Dog) en.create();//必须转型为接口,否则抛出ClassCastException
       IAnimal dog2 = (IAnimal)en.create();
       dog2.eat();
    }
说明:
由于上例中,设置了en.setSuperclass(IAnimal.class),所以en.create()方法,返回的对象,必须要转换成IAnimal接口。如果转换成Dog则会抛出ClassCastException。


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马