Java JDK与cglib动态代理有什么区别

 更新时间:2023年03月20日 09:31:26   作者:王佑辉  
这篇文章主要介绍了Java JDK动态代理和cglib动态代理的区别文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

一、说明

1.spring aop中的动态代理主要有两种方式,jdk动态代理和cglib动态代理

2.从实现接口、继承父类的角度讨论区别

3.从限制角度讨论区别

4.从性能上讨论区别

二、区别

1.jdk动态代理只提供实现接口的目标类代理,不支持没有实现接口的目标类的代理。如果目标类没有实现接口,只能用cglib代理

2.jdk动态代理会在运行时为目标类生成一个动态代理类$proxy*.class。cglib的底层是通过ASM在运行时动态生成目标类的子类,还会有其它类

3. jdk动态代理的代理类实现了目标类实现的接口,并且会实现接口所有方法来代码增强。cglib动态代理会重写父类所有的方法来代码增强

4.jdk动态代理调用时先去调用处理类进行增强,再通过反射的方式调用目标类的方法。cglib动态代理调用时先通过代理类进行增强,再直接调用父类对应的方法进行调用目标方法

5.jdk动态代理如果目标类未实现接口则无法代理,cglib是通过继承的方式来动态代理,若目标类被final关键字修饰,则无法使用cglib做动态代理

6.性能上:在老版的jdk,jdk代理生成的类速度快,通过反射调用慢,cglib是jdk代理速度的10倍左右,jdk在版本每次升级都会有很大的性能提升,cglib停滞不前,jdk7 8的动态代理性能在1万次实验中比cglib要快20%左右

三、代码示例

3.1 静态代理

package com.proxy.staticproxy;
public interface SellTicket {
    void sell();
}
package com.proxy.staticproxy;
public class TrainStation implements SellTicket{
     @Override
     public void sell() {
         System.out.println("火车站售票");
     }
 }
package com.proxy.staticproxy;
public class ProxyPoint implements SellTicket{
    //声明火车类对象
    private TrainStation trainStation = new TrainStation();
    @Override
    public void sell() {
        System.out.println("代售点收取服务费");
        trainStation.sell();
    }
    public static void main(String[] args) {
        ProxyPoint proxyPoint = new ProxyPoint();
        proxyPoint.sell();
    }
}

3.2 jdk动态代理

package com.proxy.jdkproxy;
import com.proxy.staticproxy.SellTicket;
import com.proxy.staticproxy.TrainStation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
    private TrainStation trainStation = new TrainStation();
    public SellTicket getProxyPoint() {
        /**
         * ClassLoader loader: 类加载器,用于加载代理类。可以通过目标对象获取类加载器
         * Class<?>[] interfaces: 代理类实现的接口的字节码对象
         * InvocationHandler h: 代理对象的调用处理程序
         */
        SellTicket sellTicket = (SellTicket)Proxy.newProxyInstance(trainStation.getClass().getClassLoader(), trainStation.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * @param proxy 代理对象 proxyObject是同一个对象,在invoke方法中基本不用
                     * @param method 对接口中的方法进行封装的method对象
                     * @param args 调用方法的实际参数
                     * @return 方法返回值
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    	 // 代码增强
                        System.out.println("代理点收取服务费");
                        Object object = method.invoke(trainStation, args);
                        return object;
                    }
                });
        return sellTicket;
    }
    public static void main(String[] args) {
        ProxyFactory proxyPoint = new ProxyFactory();
        SellTicket sellTicket = proxyPoint.getProxyPoint();
        sellTicket.sell();
    }
}

3.3 cglib动态代理

<!-- 引入cglib依赖包-->
<dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>2.2.2</version>
 </dependency>
package com.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyFactory implements MethodInterceptor {
    private TrainStation trainStation = new TrainStation();
    public TrainStation getTrainStation(){
        //创建Enhancer对象,类似于JDK代理中的Proxy类
        Enhancer enhancer = new Enhancer();
        //设置父类的字节码对象
        enhancer.setSuperclass(TrainStation.class);
        //设置回调函数
        enhancer.setCallback(this);
        //创建代理对象
        TrainStation trainStation = (TrainStation)enhancer.create();
        return trainStation;
    }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    	// 代码增强
        System.out.println("代售点收取服务费用");
        Object obj = method.invoke(trainStation, objects);
        return obj;
    }
    public static void main(String[] args) throws Exception {
        ProxyFactory proxyFactory = new ProxyFactory();
        TrainStation trainStation = proxyFactory.getTrainStation();
        trainStation.sell();
    }
}

到此这篇关于Java JDK与cglib动态代理有什么区别的文章就介绍到这了,更多相关Java JDK动态代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的CyclicBarrier循环栅栏详解

    Java中的CyclicBarrier循环栅栏详解

    这篇文章主要介绍了Java中的CyclicBarrier循环栅栏详解,CyclicBarrier循环栅栏是用来进行线程协作,等待线程满足某个计数,构造时设置计数个数,每个线程执行到某个需要“同步”的时刻调用 await()方法进行等待,当等待的线程数满足计数个数时,继续执行,需要的朋友可以参考下
    2023-12-12
  • 利用Spring Boot操作MongoDB的方法教程

    利用Spring Boot操作MongoDB的方法教程

    mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多,下面这篇文章主要给大家介绍了利用Spring Boot操作MongoDB的方法教程,需要的朋友可以参考下
    2017-05-05
  • 详解IDEA 中使用Maven创建项目常见错误和使用技巧(推荐)

    详解IDEA 中使用Maven创建项目常见错误和使用技巧(推荐)

    这篇文章主要介绍了详解IDEA 中使用Maven创建项目常见错误和使用技巧(推荐),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • JAVA8 lambda表达式权威教程

    JAVA8 lambda表达式权威教程

    本文主要给大家讲解Java8中最重要的一个特征之一lambda表达式,本文通过实例图文解说给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习下吧
    2021-05-05
  • Java中List集合的常用方法详解

    Java中List集合的常用方法详解

    本篇文章给大家带来的内容是关于Java中List集合的常用方法详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。下面我们就来学习一下吧
    2021-11-11
  • 基于Feign实现异步调用

    基于Feign实现异步调用

    近期,需要对之前的接口进行优化,缩短接口的响应时间,但是springcloud中的feign是不支持传递异步化的回调结果的,因此有了以下的解决方案,记录一下,需要的朋友可以参考下
    2021-05-05
  • java获取当前时间的四种方法代码实例

    java获取当前时间的四种方法代码实例

    这篇文章主要介绍了java获取当前时间的四种方法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • spring boot整合redis实现shiro的分布式session共享的方法

    spring boot整合redis实现shiro的分布式session共享的方法

    本篇文章主要介绍了spring boot整合redis实现shiro的分布式session共享的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • java实现JSON字符串格式化输出

    java实现JSON字符串格式化输出

    这篇文章主要为大家详细介绍了如何使用java实现JSON字符串格式化输出,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以了解下
    2024-01-01
  • 仿京东平台框架开发开放平台(包含需求,服务端代码,SDK代码)

    仿京东平台框架开发开放平台(包含需求,服务端代码,SDK代码)

    现在开放平台越来越多了,下面针对仿京东开放平台框架,封装自己的开放平台,分享给大家。先感谢一下京东开放平台的技术大佬们,下面从开放平台需求,服务端代码,SDK代码三大块进行分享
    2021-06-06

最新评论