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


          相关文章
          |
          4月前
          |
          监控 安全 Java
          |
          8月前
          |
          Java Spring
          JDK动态代理和CGLIB动态代理的区别
          Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理: ● JDK动态代理只提供接口的代理,不支持类的代理Proxy.newProxyInstance(类加载器, 代理对象实现的所有接口, 代理执行器) ● CGLIB是通过继承的方式做的动态代理 , 如果某个类被标记为final,那么它是无法使用 CGLIB做动态代理的。Enhancer.create(父类的字节码对象, 代理执行器)
          |
          8月前
          |
          监控 Java API
          JDK动态代理和CGLIB动态代理
          Java动态代理允许在运行时创建代理对象,增强或拦截目标类方法的执行。主要通过两种方式实现:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口,利用`java.lang.reflect.Proxy`类和`InvocationHandler`接口;CGLIB则通过字节码技术生成目标类的子类作为代理,适用于未实现接口的类。两者均用于在方法执行前后添加额外逻辑,如日志记录、权限控制等,广泛应用于AOP框架中。
          301 2
          |
          9月前
          |
          监控 Java API
          JDK动态代理和CGLIB动态代理
          Java动态代理允许在运行时创建代理对象,增强或拦截目标类的方法调用,无需修改原代码。它有两种主要实现方式:JDK动态代理和CGLIB动态代理。 - **JDK动态代理**:通过`java.lang.reflect.Proxy`类和`InvocationHandler`接口实现,适用于实现了接口的类。它在方法调用前后插入额外逻辑,如日志记录、权限控制等。 - **CGLIB动态代理**:基于字节码技术,为未实现接口的类生成子类作为代理,重写父类方法以添加增强逻辑。适用于没有接口的类,但要求目标类不能是`final`类或方法。
          134 1
          |
          9月前
          |
          Java API 数据安全/隐私保护
          探索Java动态代理的奥秘:JDK vs CGLIB
          动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
          286 0
          探索Java动态代理的奥秘:JDK vs CGLIB
          |
          存储 缓存 Java
          Spring高手之路23——AOP触发机制与代理逻辑的执行
          本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
          305 3
          Spring高手之路23——AOP触发机制与代理逻辑的执行
          |
          安全 Java 开发者
          AOP中的JDK动态代理与CGLIB动态代理:深度解析与实战模拟
          【11月更文挑战第21天】面向切面编程(AOP,Aspect-Oriented Programming)是一种编程范式,它通过将横切关注点(cross-cutting concerns)与业务逻辑分离,以提高代码的可维护性和可重用性。在Java开发中,AOP的实现离不开动态代理技术,其中JDK动态代理和CGLIB动态代理是两种常用的方式。本文将从背景、历史、功能点、业务场景、底层逻辑等多个维度,深度解析这两种代理方式的区别,并通过Java示例进行模拟和比较。
          825 5
          |
          4月前
          |
          存储 Ubuntu 安全
          在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
          在整个安装过程中,你可能需要管理员权限,因此你可能要使用 `sudo` 来获取必要的权限。记得做完每一个步骤后,都要检查输出,以确保没有发生错误,并且每项操作都成功完成。如果在安装过程中遇到问题,查看 `/var/log/` 下的日志文件对于问题的解决可能是有帮助的。
          307 21
          |
          4月前
          |
          IDE Ubuntu Java
          在Ubuntu18.04安装兼容JDK 8的Eclipse集成开发环境的指南。
          完成以上步骤后,您将在Ubuntu 18.04系统上成功安装并配置了Eclipse IDE,它将与JDK 8兼容,可以开始进行Java开发工作。如果遇到任何问题,请确保每一步骤都正确执行,并检查是否所有路径都与您的具体情况相匹配。
          207 11

          热门文章

          最新文章