您好,欢迎来到化拓教育网。
搜索
您的当前位置:首页Spring系列七:JDK 动态代理和 CGLIB 代理

Spring系列七:JDK 动态代理和 CGLIB 代理

来源:化拓教育网

21.说说JDK 动态代理和 CGLIB 代理 ?

Spring的AOP是通过来实现的,动态代理主要有两种方式JDK动态代理和Cglib动态代理,这两种动态代理的使用和原理有些不同。

JDK 动态代理

CgLib 动态代理

  1. 使用JDK创建代理有一大,它只能为接口创建代理实例,而CgLib 动态代理就没有这个。

  2. CgLib 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

  3. CgLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

我们来看一个常见的小场景,客服中转,解决用户问题:

用户向客服提问题

JDK动态代理实现:

JDK动态代理类图

  • 接口

    public interface ISolver {
        void solve();
    }
    
  • 目标类:需要实现对应接口

    public class Solver implements ISolver {
        @Override
        public void solve() {
            System.out.println("疯狂掉头发解决问题……");
        }
    }
    
  • 态代理工厂:ProxyFactory,直接用反射方式生成一个目标对象的代理对象,这里用了一个匿名内部类方式重写InvocationHandler方法,实现接口重写也差不多

    public class ProxyFactory {
    
        // 维护一个目标对象
        private Object target;
    
        public ProxyFactory(Object target) {
            this.target = target;
        }
    
        // 为目标对象生成代理对象
        public Object getProxyInstance() {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("请问有什么可以帮到您?");
    
                            // 调用目标对象方法
                            Object returnValue = method.invoke(target, args);
    
                            System.out.println("问题已经解决啦!");
                            return null;
                        }
                    });
        }
    }
    
  • 客户端:Client,生成一个代理对象实例,通过代理对象调用目标对象方法

    public class Client {
        public static void main(String[] args) {
            //目标对象:程序员
            ISolver developer = new Solver();
            //代理:客服小姐姐
            ISolver csProxy = (ISolver) new ProxyFactory(developer).getProxyInstance();
            //目标方法:解决问题
            csProxy.solve();
        }
    }
    

Cglib动态代理实现:

Cglib动态代理类图

  • 目标类:Solver,这里目标类不用再实现接口。

    public class Solver {
    
        public void solve() {
            System.out.println("疯狂掉头发解决问题……");
        }
    }
    
  • 动态代理工厂:

    public class ProxyFactory implements MethodInterceptor {
    
       //维护一个目标对象
        private Object target;
    
        public ProxyFactory(Object target) {
            this.target = target;
        }
    
        //为目标对象生成代理对象
        public Object getProxyInstance() {
            //工具类
            Enhancer en = new Enhancer();
            //设置父类
            en.setSuperclass(target.getClass());
            //设置回调函数
            en.setCallback(this);
            //创建子类对象代理
            return en.create();
        }
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("请问有什么可以帮到您?");
            // 执行目标对象的方法
            Object returnValue = method.invoke(target, args);
            System.out.println("问题已经解决啦!");
            return null;
        }
    
    }
    
  • 客户端:Client

    public class Client {
        public static void main(String[] args) {
            //目标对象:程序员
            Solver developer = new Solver();
            //代理:客服小姐姐
            Solver csProxy = (Solver) new ProxyFactory(developer).getProxyInstance();
            //目标方法:解决问题
            csProxy.solve();
        }
    }
    

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo9.cn 版权所有 赣ICP备2023008801号-1

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务