spring5为什么走cglib

fiy 其他 42

回复

共3条回复 我来回复
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Spring是一个非常流行的Java开发框架,它提供了许多便捷的功能和特性,其中包括依赖注入(Dependency Injection)和面向切面编程(Aspect-Oriented Programming)等。在Spring中,使用代理模式来实现依赖注入和AOP功能。而在代理模式中,有两种常见的实现方式:JDK动态代理和CGLIB代理。

    JDK动态代理是通过Java的反射机制来实现的,它要求被代理的类必须实现接口。当应用程序需要生成一个代理对象时,JDK动态代理会在运行时通过反射动态地创建一个实现该接口的代理类,并在代理类的方法中调用被代理类的相应方法。这种方式在一些场景下非常有用,但也有一些限制。最明显的限制是被代理类必须实现接口,这对于一些没有实现接口的类而言是不可行的。

    而CGLIB是一个强大的字节码生成库,它可以在运行时动态生成指定类的子类。相比于JDK动态代理,CGLIB没有对被代理类实现接口的限制,它能够代理任意的类。CGLIB通过继承被代理类,并重写其中的方法来实现代理功能。当应用程序需要生成一个代理对象时,CGLIB会继承被代理类并重写其中的方法,在重写的方法中调用被代理类的相应方法。这种方式可以在运行时生成一个和被代理类功能相同的子类,从而实现代理功能。

    Spring选择使用CGLIB作为默认的代理方式,主要是出于以下几个考虑:

    1. CGLIB更加灵活:CGLIB不需要被代理类实现接口,可以代理任意的类,这样就能够更加灵活地应对不同的场景。
    2. CGLIB更加强大:CGLIB可以生成继承自被代理类的子类,通过继承并重写方法的方式实现代理功能,这样可以更加灵活地对被代理类进行增强。
    3. CGLIB性能更高:相比于JDK动态代理,CGLIB在生成代理对象的过程中,不需要通过反射调用被代理类的构造方法和方法,所以它的性能更高一些。

    总而言之,Spring选择走CGLIB作为默认的代理方式,主要是出于CGLIB对非接口类的代理更加灵活和强大,以及对性能的一些优化考虑。但在某些情况下,如被代理类已经实现了接口或者需要更高的性能,也可以通过配置强制使用JDK动态代理。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring5选择使用CGLib作为默认的动态代理实现,主要是因为以下几个原因:

    1. 性能优势:CGLib相对于JDK的动态代理来说,性能更好。CGLib使用字节码生成器,在运行时生成代理类的字节码,然后通过ClassLoader加载字节码。相比之下,JDK的动态代理是通过实现接口的方式来生成代理类,性能较低。

    2. 支持非接口类代理:CGLib可以代理没有实现接口的类,而JDK的动态代理只能代理实现了接口的类。这使得使用CGLib更加灵活,可以代理更多种类的对象。

    3. 更简洁的代码:使用CGLib进行代理不需要编写接口,只需要编写被代理类即可,简化了开发过程。同时,CGLib也提供了更多的功能,如方法拦截、方法回调等,可以更方便地实现AOP的功能。

    4. 兼容性:由于CGLib是通过字节码生成器动态生成代理类,与JDK的动态代理相比,它可以完全兼容所有的ClassLoader。这意味着,无论是在传统的Java应用程序中,还是在各种容器和框架中使用Spring5,CGLib都可以正常工作。

    5. 增强功能:CGLib不仅可以代理类的方法,还可以代理类的属性,并对它们进行增强。这为Spring5提供了更多的AOP功能,使得开发人员可以更加灵活地进行切面编程,并实现更复杂的业务逻辑。

    1年前 0条评论
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    一、Spring框架中的动态代理方式
    Spring框架提供了两种类型的动态代理方式:基于接口的JDK动态代理和基于类的CGLIB动态代理。在选择使用哪种方式时,Spring会根据不同的情况进行处理。

    二、JDK动态代理
    JDK动态代理是基于接口的代理方式,它利用Java的反射机制生成代理类。该代理类实现了目标接口,并将方法调用委托给实际的目标对象进行处理。

    JDK动态代理的实现原理:

    1. 定义一个接口,该接口中定义了需要被代理的方法。
    2. 创建一个InvocationHandler接口的实现类,并重写其invoke方法,该方法中定义了代理对象实际执行的操作。
    3. 使用Proxy类的newProxyInstance方法,传入ClassLoader、代理接口数组以及InvocationHandler实现类,生成代理类的字节码文件。
    4. 使用newInstance方法实例化代理类,然后通过代理类调用需要被代理的方法。

    JDK动态代理的优势:

    1. JDK动态代理只需要实现目标接口,不需要继承具体的代理类,更加灵活。
    2. 使用JDK动态代理时,无法为final修饰的类和private修饰的方法生成代理。

    JDK动态代理的局限性:

    1. JDK动态代理只能对实现了接口的类进行代理,对于没有实现接口的类,无法进行代理。
    2. JDK动态代理的性能相对较低,因为它需要通过反射机制生成代理类的字节码文件。

    三、CGLIB动态代理
    CGLIB动态代理是基于类的代理方式,它通过继承目标类并重写其中的方法来实现代理。由于CGLIB动态代理是通过继承的方式,所以无论目标类是否实现了接口都可以实现代理。

    CGLIB动态代理的实现原理:

    1. 创建Enhancer类的实例。
    2. 设置Enhancer的父类为目标类,即需要被代理的类。
    3. 设置Callback接口的实现类,该类中定义了具体的代理逻辑。
    4. 调用Enhancer类的create方法,生成代理类的实例。

    CGLIB动态代理的优势:

    1. CGLIB动态代理可以代理没有实现接口的类。
    2. CGLIB动态代理可以为final修饰的类和private修饰的方法生成代理。

    CGLIB动态代理的局限性:

    1. CGLIB动态代理的代理对象是目标类的子类,当目标类是final修饰的时候,无法进行代理。
    2. CGLIB动态代理的性能相对较高,因为它通过继承的方式生成代理类,无需使用反射机制。

    四、Spring为何选择CGLIB动态代理
    在Spring5版本中,默认情况下,如果目标类没有实现接口,则Spring会使用CGLIB动态代理方式生成代理类。这是由于CGLIB动态代理方式在性能方面更好,无论是生成代理类还是执行代理操作都相对更快。

    在Spring中,如果需要使用JDK动态代理方式生成代理类,可以通过设置配置项进行切换。在配置文件中使用<aop:aspectj-autoproxy proxy-target-class="true"/>,即可启用基于类的CGLIB动态代理方式。

    总结:
    Spring框架中可以通过选择JDK动态代理或CGLIB动态代理来生成代理对象。JDK动态代理适用于接口代理,而CGLIB动态代理适用于类代理。在Spring5中,默认情况下,如果目标类没有实现接口,则会使用CGLIB动态代理方式,提高了性能。如果需要使用JDK动态代理方式,可以通过配置进行切换。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部