一、cglib代理介绍

cglib代理是实现动态代理的另一种方式,CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择

二、cglib的原理

  1. 动态生成目标类的代理类,重写代理类的所有非final修饰的方法,子类使用方法拦截的方式实现目标类的增强,所以cglib代理比jdk反射代理效率更高,并且能代理类,而jdk代理只能代理接口
  2. 底层使用asm字节码框架生成代理类,而不是使用反射生成类
  3. 缺点不能代理被final修饰的方法

    三、cglib代理的实现

    public static void main(String[] args) {
         System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "resource");
         Dog dog =new Dog();
         Enhancer enhancer =new Enhancer();
         //设置目前类
         enhancer.setSuperclass(Dog.class);
         //设置拦截器
         enhancer.setCallback(new MethodInterceptor() {
             public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                 System.out.println("呵呵,我是增强");
                 return  methodProxy.invokeSuper(o,objects);
             }
         });
         Dog dogProxy = (Dog) enhancer.create();
         dogProxy.run();
     }
    

四、invokeSuper()方法

因为cglib代理是继承目标类,并且重写方法,所以这里调用invokesuper方法,调用父类的方法

五、cglib原理

image.png
上图可以看到cglib方式会在内存中生成,3个字节码文件.可以使用 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, “resource”);方法将字节码文件写到相关目录。

  1. 可以看到代理类实现了目标代理类
    image.png
  2. 可以看到重写run方法,先回去回调方法,如果获取不到就加载回调方法,执行intercept 方法
    image.png
  3. FastClass机制
    FastClass提出了index下标的概念,通过index保存方法的引用信息,将反射调用转化为方法的直接调用,体现所谓的fast
    image.png
  4. 通过方法名计算hashcode值,通过hashcode找到方法对应的index
  5. 通过index 调用invoke方法,invoke方法通过index判断执行那个方法

总结

  1. 动态代理类通过实现invocationHandler接口
  2. 通过
    Proxy.newProxyInstance(factory.getClass().getClassLoader(),person.getClass().getInterfaces(),this)方法
    复制一份代理的类并且生成字节码文件到内存中,
    生成的代理类 继承了Proxy类 并且实现了代理接口
    调用生成的动态代理类中实现的方法,其中调用了其实现的方法,在方法中通过invocationHandler的invoke()方法
    jdk动态代理的缺点 不能代理类,需要实现invocationHandler接口
    jdk动态代理和cglib生成字节码的方式不通
  3. cglib动态代理 可以动态代理类
    因为cglib动态生成的类是继承原类,所以可以动态代理到类
  4. jdk动态代理实现了自己的顶层接口继承了proxy类