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

简介: ​21.说说JDK 动态代理和 CGLIB 代理 ?Spring的AOP是通过动态代理来实现的,动态代理主要有两种方式JDK动态代理和Cglib动态代理,这两种动态代理的使用和原理有些不同。JDK 动态代理CgLib 动态代理我们来看一个常见的小场景,客服中转,解决用户问题:用户向客服提问题JDK动态代理实现:JDK动态代理类图public interface ISolver {    void solve();}public class Solver implements ISolver {    @Override    pu

  JDK相信小伙伴们对它十分熟悉,那么小伙伴们知道JDK动态代理和CGLIB代理的区别吗?接下来由叶秋学长带领小伙伴对它们进行深入学习吧~~

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

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

JDK 动态代理

    1. Interface:对于 JDK 动态代理,目标类需要实现一个Interface。
    2. InvocationHandler:InvocationHandler是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。
    3. Proxy:Proxy利用InvocationHandler动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。

    CgLib 动态代理

      1. 使用JDK创建代理有一大限制,它只能为接口创建代理实例,而CgLib 动态代理就没有这个限制。
      2. CgLib 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
      3. CgLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

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

      image.gif编辑

      用户向客服提问题

      JDK动态代理实现:

      image.gif编辑

      JDK动态代理类图

        • 接口
        public interface ISolver {
            void solve();
        }
        • image.gif
        • 目标类:需要实现对应接口
        public class Solver implements ISolver {
            @Override
            public void solve() {
                System.out.println("疯狂掉头发解决问题……");
            }
        }
        • image.gif
        • 态代理工厂: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;
                            }
                        });
            }
        }
        • image.gif
        • 客户端:Client,生成一个代理对象实例,通过代理对象调用目标对象方法
        public class Client {
            public static void main(String[] args) {
                //目标对象:程序员
                ISolver developer = new Solver();
                //代理:客服小姐姐
                ISolver csProxy = (ISolver) new ProxyFactory(developer).getProxyInstance();
                //目标方法:解决问题
                csProxy.solve();
            }
        }
        • image.gif

        Cglib动态代理实现:

        image.gif编辑

        Cglib动态代理类图

          • 目标类:Solver,这里目标类不用再实现接口。
          public class Solver {
              public void solve() {
                  System.out.println("疯狂掉头发解决问题……");
              }
          }
          • image.gif
          • 动态代理工厂:
          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;
              }
          }
          • image.gif
          • 客户端:Client
          public class Client {
              public static void main(String[] args) {
                  //目标对象:程序员
                  Solver developer = new Solver();
                  //代理:客服小姐姐
                  Solver csProxy = (Solver) new ProxyFactory(developer).getProxyInstance();
                  //目标方法:解决问题
                  csProxy.solve();
              }
          }
          • image.gif


          相关文章
          |
          28天前
          |
          存储 缓存 Java
          Spring高手之路23——AOP触发机制与代理逻辑的执行
          本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
          35 3
          Spring高手之路23——AOP触发机制与代理逻辑的执行
          |
          21天前
          |
          设计模式 Java API
          [Java]静态代理与动态代理(基于JDK1.8)
          本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
          17 0
          [Java]静态代理与动态代理(基于JDK1.8)
          |
          28天前
          |
          Java 数据安全/隐私保护 Spring
          Spring进阶:初识动态代理
          本文介绍了Spring框架中AOP切面编程的基础——动态代理。通过定义Vehicle接口及其实现类Car和Ship,展示了如何使用动态代理在不修改原代码的基础上增强功能。文章详细解释了动态代理的工作原理,包括通过`Proxy.newProxyInstance()`方法创建代理对象,以及`InvocationHandler`接口中的`invoke()`方法如何处理代理对象的方法调用。最后,通过一个测试类`TestVehicle`演示了动态代理的具体应用。
          |
          1月前
          |
          Java
          【编程进阶知识】静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例
          本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。
          18 1
          |
          2月前
          |
          设计模式 Java 测试技术
          spring复习04,静态代理动态代理,AOP
          这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
          spring复习04,静态代理动态代理,AOP
          |
          1月前
          |
          Java 关系型数据库 开发工具
          idea创建不了spring2.X版本,无法使用JDK8,最低支持JDK17 , 如何用idea创建spring2.X版本,使用JDK8解决方案
          本文提供了解决方案,如何在IDEA中创建Spring 2.X版本的项目并使用JDK8,尽管Spring 2.X已停止维护且IDEA不再直接支持,通过修改pom.xml或使用阿里云的国内源来创建项目。
          73 0
          idea创建不了spring2.X版本,无法使用JDK8,最低支持JDK17 , 如何用idea创建spring2.X版本,使用JDK8解决方案
          |
          2月前
          |
          设计模式 Java Spring
          spring源码设计模式分析-代理设计模式(二)
          spring源码设计模式分析-代理设计模式(二)
          |
          Java Spring
          SSM-Spring-10:Spring中cglib动态代理
          ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------   何为动态代理,就不扯皮了,上一篇博客刚刚提到,那cglib动态代理又怎么写,我拿个和上个例子相似的案例来写   具体案例:   一个SomeServiceImpl接口 package cn.
          1162 0
          |
          2月前
          |
          SQL 监控 druid
          springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
          这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
          |
          1月前
          |
          人工智能 自然语言处理 前端开发
          SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
          【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
          162 2