zoukankan      html  css  js  c++  java
  • cglib实现动态代理简单使用

    Boss:

    package proxy.cglib;
    
    
    public class Boss{
        public void findPerson() {
            System.out.println("我要找java架构师");
        }
    }

    WebApp:

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 方法拦截器
     * CGLib 代理的目标对象不需要实现任何接口,它是通过动态继承目标对象 实现的动态代理
     */
    public class WebApp implements MethodInterceptor {
        public Object getInstance(Class<?> clazz){
            Enhancer enhancer = new Enhancer();
            //告诉cglib,生成的子类需要继承哪个类
            enhancer.setSuperclass(clazz);
            //设置回调
            enhancer.setCallback(this);
            //生成源代码
            //编译成class文件
            //加载到JVM中,并返回被代理对象
            return enhancer.create();
        }
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            //这个obj的引用是由CGLib给我们new出来的
            //cglib new出来以后的对象,是被代理对象的子类
            //在new子类之前,实际上默认先调用了我们super()方法的,
            //new子类的同时,必须先new出来父类,这就相当于是间接的持有了我们父类的引用
            //子类重写了父类的所有的方法
            //我们改变子类对象的某些属性,是可以间接的操作父类的属性的
            before();
            Object obj = methodProxy.invokeSuper(o, objects);//这里是调父类的(子类死循环)
            after();
            return obj;
        }
        private void after() {
            System.out.println("---------------");
        }
    
        private void before() {
            System.out.println("找Person,找我WebApp cglib");
            System.out.println("---------------");
        }
    }

    Test:

    package proxy.cglib;
    
    /**
     * JDK的动态代理是通过接口来进行强制转换的
     * 生成以后的代理对象,可以强制转换为接口
     *
     *CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法
     * 生成以后的对象,可以强制转换为被代理对象
     * 子类引用赋值给父类
     */
    public class Test {
        public static void main(String[] args){
            try {
                Boss boss = (Boss) new WebApp().getInstance(Boss.class);
                boss.findPerson();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    将 CGLib 代理 后的 class 写入到磁盘,然后,我们再反编译一探究竟

     

    CGLib 和 JDK 动态代理对比
    1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。

    2.JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
    3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高 

  • 相关阅读:
    C语言博客作业01分支、顺序结构
    vue学习日记04
    vue学习日记01
    vue学习日记05
    vue学习日记02
    企业微信小程序注册遇到的一些事
    vue学习日记03
    Unix/Linux系统编程第十三章学习笔记
    OpenEuler 中C与汇编的混合编程(选做)
    《Unix/Linux系统编程》第五章学习笔记
  • 原文地址:https://www.cnblogs.com/fly-book/p/10361846.html
Copyright © 2011-2022 走看看