spring5为什么走cglib

fiy 其他 36

回复

共3条回复 我来回复
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Spring5走CGLIB主要是基于以下几个原因:

    1. JDK动态代理的限制:JDK动态代理只能对实现了接口的类生成代理对象,对于没有实现接口的类无法使用JDK动态代理。而CGLIB是针对类来实现代理,无论是否实现接口都能够正确生成代理对象。

    2. 性能优势:相比JDK动态代理,在进行代理对象的方法调用时,CGLIB采用了FastClass机制,它通过直接调用方法的方式来提高了性能,省去了反射调用的开销,所以在性能上更加优于JDK动态代理。

    3. Spring AOP的默认选择:Spring AOP默认使用CGLIB来生成代理对象。当被代理的类没有实现接口时,Spring会自动选择使用CGLIB来生成代理对象,这也是为了提供更好的性能。

    4. 功能增强:CGLIB可以对类的方法进行增强,比如对方法进行拦截、增加额外的逻辑等。这使得使用CGLIB能够更加方便地实现一些功能,如事务管理、日志记录等。

    总结来说,Spring5选择走CGLIB主要是为了解决JDK动态代理的限制,并提供更好的性能和功能增强。通过使用CGLIB,Spring能够更灵活地创建代理对象,并且能够在不需要实现接口的情况下生成代理对象,为开发者提供更好的编程体验和性能优势。

    1年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    Spring 5 选择使用 CGLIB 作为默认的代理方式,而不是 JDK 动态代理。这是因为 CGLIB 在某些情况下提供了比 JDK 动态代理更好的性能,并且支持更广泛的代理功能。

    1. 性能优势:JDK 动态代理通过反射来创建和调用代理对象的方法,这个过程相对较慢,而且生成的代理类的性能较低。相比之下,CGLIB 是通过生成目标类的子类来实现代理,因此不需要使用反射,其性能会更好。

    2. 对接口的限制:JDK 动态代理只能代理实现了接口的类,而无法代理没有实现接口的类。而 CGLIB 则可以代理任何类,包括没有实现接口的类。

    3. 方法拦截:CGLIB 可以对类的所有方法进行拦截,而 JDK 动态代理只能对接口中定义的方法进行拦截。这使得在使用 CGLIB 时可以更精细地控制方法的调用。

    4. 构造函数代理:CGLIB 可以代理目标类的构造函数,而 JDK 动态代理不支持对构造函数的代理。

    5. 第三方库支持:CGLIB 是一个成熟的、广泛使用的第三方库,已经被证明是稳定可靠的。在选择 CGLIB 作为默认的代理方式时,Spring 可以依靠 CGLIB 的稳定性和可靠性。

    总的来说,Spring 5 选择使用 CGLIB 作为默认的代理方式是为了提供更好的性能和更广泛的代理功能,同时也符合 Spring 的设计理念,即提供灵活而功能强大的代理能力。

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

    Spring是一个开源的企业级应用开发框架,它提供了一个轻量级的容器来管理Java对象的生命周期,并通过依赖注入(DI)实现了对象之间的松耦合。在Spring中,有两种主要的代理技术:JDK动态代理和CGLIB代理。

    首先,我们需要了解一下动态代理是什么。动态代理是一种在运行时生成代理对象的方式,它不需要提前编写代理类,而是通过使用一个中间类来生成代理对象。这个中间类可以根据需要在运行时生成代理类,并在代理类中“拦截”对目标对象的方法调用。

    在Spring中,当我们创建一个基于接口的代理对象时,它会使用JDK动态代理来生成代理类。但是,当目标类没有实现接口时,Spring会自动选择使用CGLIB代理。CGLIB(Code Generation Library,代码生成库)是一个强大的字节码生成库,它可以在运行时动态生成目标类的子类,并重写其中的方法来实现代理功能。

    为什么Spring选择使用CGLIB代理而不是JDK动态代理呢?这是因为JDK动态代理只能对实现了接口的类进行代理,而不能对没有实现接口的类进行代理。而CGLIB代理则可以对任意类进行代理,包括没有实现接口的类。

    下面是使用CGLIB代理的步骤:

    1. 首先,我们需要将CGLIB库添加到项目的依赖中。
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
    
    1. 然后,我们需要创建一个类来实现MethodInterceptor接口,并重写其中的intercept方法。在这个方法中,我们可以定义对目标对象方法的增强逻辑。
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    
    public class MyInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // 增强逻辑
            // 调用目标对象的方法
            Object result = proxy.invokeSuper(obj, args);
            // 更多增强逻辑
            return result;
        }
    }
    
    1. 接下来,我们需要在Spring配置文件中声明一个bean来创建代理对象。在配置文件中,我们可以通过<aop:config>元素来配置切面和通知。
    <aop:config>
        <aop:advisor advice-ref="myInterceptor" pointcut="execution(* com.example.MyService.*(..))"/>
    </aop:config>
    <bean id="myService" class="com.example.MyServiceImpl">
        <aop:scoped-proxy/>
    </bean>
    
    <bean id="myInterceptor" class="com.example.MyInterceptor"/>
    

    在上面的配置中,<aop:advisor>元素用于配置切面和通知。advice-ref属性指定了使用的Advice(通知)对象,而pointcut属性指定了切入点表达式,即需要被代理的目标方法。<bean>元素用于创建目标对象,并通过<aop:scoped-proxy>元素来指定使用CGLIB代理。

    通过以上步骤,我们就可以在Spring中使用CGLIB代理来创建代理对象。这样,无论目标对象是否实现接口,都可以通过代理对象来实现方法的增强和拦截。

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

400-800-1024

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

分享本页
返回顶部