JDK动态代理和cglib代理

news2024/11/27 3:58:30

文章目录

  • 前言
  • 1.JDK动态代理
    • 1.1 定义一个接口
    • 1.2 实现接口
    • 1.3 自定义MyInvocationHandler去实现InvocationHandler接口
    • 1.4 测试jdk代理
    • 1.5 输出代理类
  • 2.cglib代理
    • 2.1 代理接口类
    • 2.2 代理普通类
    • 2.3 设置属性生成cglib代理类

前言

动态代理在平时的开发中用的也很多,统计接口调用耗时,日志功能,增强功能实现等。代理主要有两种 代理方式:
JDK动态代理特征

    1. 只能为接口创建代理对象
    1. 创建出来的代理都是java.lang.reflect.Proxy的子类

cglib代理
jdk动态代理只能代理接口类,cglib可以代理接口和普通类,通过子类来对被代理类实现增强扩展。

1.JDK动态代理

比如我们要统计某个方法的执行消耗的时间

1.1 定义一个接口

/**
 * 定义接口
 */
public interface IMyService {
    void method1();
}

1.2 实现接口

/**
 * 实现接口
 */
public class MyService implements IMyService {
    @Override
    public void method1() {
        System.out.println("method1 invokeed....");
    }
}

1.3 自定义MyInvocationHandler去实现InvocationHandler接口

/**
 * 自定义InvocationHandler
 */
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    //传入代理的目标类 
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startime = System.nanoTime();
        Object result = method.invoke(this.target, args); //将请求转发给target去处理
        long endTime = System.nanoTime();
        System.out.println(method + ",耗时(纳秒):" + ( endTime- startime));
        return result;
    }
}

1.4 测试jdk代理

public class TestProxy {
    public static void main(String[] args) {
        //1.创建被代理类
        IMyService service = new MyService();
        //2.自定义InvocationHandler
        MyInvocationHandler invocationHandler = new MyInvocationHandler(service);
        //3.利用Proxy创建代理对象
        Object proxyObject = Proxy.newProxyInstance(service.getClass().getClassLoader(), new Class[]{IMyService.class}, invocationHandler);
        //4.执行代理方法
        IMyService proxyService = (IMyService) proxyObject;
        //5.执行方法
        proxyService.method1();
    }
}

测试结果

1.5 输出代理类

///加属性
//设置属性生成代理类
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

再次执行方法会生成一个 代理类 :
代理类

public final class $Proxy0 extends Proxy implements IMyService {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void method1() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.elite.javaee.service.IMyService").getMethod("method1");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

可以看到生成代理类 ,集成了Proxy并实现了代理的接口,代理类的方法有4个,其他的都是默认的方法,m3是代理生成的。

2.cglib代理

jdk代理需要的缺点是只能代理接口类,而cglib不一样 ,可以代理普通的类,是通过增强扩展实现,相当于创建一个被代理类的子类,能够重写父类方法,也是符合设计原则中的里式替换原则。

2.1 代理接口类

public class TestCglibProxy {
    public static void main(String[] args) {
        //1.创建一个enhancer类
        /**
         * Generates dynamic subclasses to enable method interception.
         * This class started as a substitute for the standard Dynamic Proxy support included with JDK 1.3,
         * but one that allowed the proxies to extend a concrete base class,
         * in addition to implementing interfaces. T
         * he dynamically generated subclasses override the non-final methods of the superclass and have hooks which callback to user-defined interceptor implementations.
         * The original and most general callback type is the MethodInterceptor, which in AOP terms enables "around advice"--that is, you can invoke custom code both before and after the invocation of the "super" method.
         * In addition you can modify the arguments before calling the super method, or not call it at all.
         * Although MethodInterceptor is generic enough to meet any interception need, it is often overkill.
         * For simplicity and performance, additional specialized callback types, such as LazyLoader are also available.
         * Often a single callback will be used per enhanced class, but you can control which callback is used on a per-method basis with a CallbackFilter.
         * The most common uses of this class are embodied in the static helper methods.
         * For advanced needs, such as customizing the ClassLoader to use, you should create a new instance of Enhancer.
         * Other classes within CGLIB follow a similar pattern.
         * All enhanced objects implement the Factory interface,
         * unless setUseFactory is used to explicitly disable this feature.
         * The Factory interface provides an API to change the callbacks of an existing object,
         * as well as a faster and easier way to create new instances of the same type.
         */
        Enhancer enhancer = new Enhancer();
        //2.设置代理的类
        enhancer.setInterfaces(new Class[]{IMyService.class});
       //2.通过设置callback来代理拦截的方法
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("cglib代理的方法==》"+method.getName());
                return null;
            }
        });
        IMyService proxyService = (IMyService) enhancer.create();
        proxyService.method1();

    }
}


2.2 代理普通类

其他代码都一致

 //设置代理的父类
enhancer.setSuperclass(Service.class);

Service service = (Service) enhancer.create();
service.method2();

2.3 设置属性生成cglib代理类

 //设置属性生成代理类
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\devproject\\devcode\\code\\SSMCollection\\com\\sun\\proxy");
      

可以看到生成的代理类去调用父类也就是被代理类的方法。
子类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/629262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法与数据结构(五)

一、c二叉树结构 typedef struct BiNode {int data; //结点内值域struct BiNode* lchild, * rchild; //左孩子 右孩子 } BiNode, * BiTree;或者: class Node { public:char data;// data表示该节点代表的内容;Node* L;//左子树Node* R;//右子树 }; No…

深度学习之卷积神经网络识别图片验证码实战案例(十)

案例背景:程序自动化的爬虫而无需人工介入是我们的最终目标。自动化爬虫避免不了自动登录的问题,在爬取XX数据的过程中,遇到登录图形验证码的识别的问题,那我们该如何攻破这种验证码呢? 字符验证码图片如下&#xff1a…

facenet, dlib人脸识别,人体检测,云数据库mysql,QQ邮箱,手机验证码,语音播报

目录 部分代码展示: 录入部分 识别部分​编辑 活体检测部分​编辑 同步到云数据库MySQL 其他操作 部分图片展示: 完整代码加ui链接: 涉及到的一些知识点的文章 部分代码展示: 录入部分 识别部分 活体检测部分 同步到云数…

峰终定律原理

峰终定律 峰终定律( Peak–End Rule),是由丹尼尔卡尼曼(2002年诺贝尔经济学奖获得者,心理学家)提出的。 模型介绍 峰终定律是指如果在一段体验的高峰和结尾,体验是愉悦的,那么对整个…

走进机器学习

作者简介:本人是一名大二学生,就读于人工智能专业,学习过c,c,java,python,Mysql等编程知识,现在致力于学习人工智能方面的知识,感谢CSDN让我们相遇,我也会致力…

javaScript蓝桥杯---传送门

目录 一、介绍二、准备三、目标四、代码五、知识点六、完成 一、介绍 日常浏览网页的时候,我们会发现一个问题,当页面太长、内容太多的时候我们很难快速浏览到心仪的内容。为了解决这个烦恼,优秀的产品研发团队发明了一种类似传送门的功能&a…

对比分析:黑盒测试 VS 白盒测试

一、引言 在软件开发过程中,测试是确保产品质量的关键环节。其中,黑盒测试和白盒测试是两种常见的测试方法。本文将详细解析这两种测试方法的定义、特点,同时通过具体示例进行对比分析。 二、黑盒测试 黑盒测试,又称功能测试&…

2023最新性能测试面试题合集含答案,看完拿个20Koffer不是问题

1、描述一下你们公司的性能测试流程? 1)分析性能需求(用户使用最频繁的场景进行测试)确定性能指标(例如:事务通过率100%,top99%是5秒,最大并发是2000,CPU和内存都是70%以…

Git教程笔记

概念 Git是一个分布式版本控制工具,主要用于管理开发过程中的源代码文件(Java类、xml文件、html页面等)在软件开发过程中被广泛使用。 Git常用命令 Git全局设置 获取Git仓库 工作区、暂存区、版本库 概念 Git工作区中文件的状态 工作区中…

ROS EKF 机器人位姿估计功能包:robot_pose_ekf | 仿真环境实践

ROS EKF 机器人位姿估计功能包&#xff1a;robot_pose_ekf | 仿真环境实践 在仿真下使用robot_pose_ekf 在仿真下使用robot_pose_ekf 仿真环境为 一个无人机&#xff0c;具备3D POSE里程计数据&#xff0c;和imu数据。 将robot_pose_ekf.launch文件进行如下更改 <launc…

C++ unordered_map 性能优化

一 插入加速 unordered_map 在桶满时自动进行 rehash 操作。手动调用 rehash 函数可以手动调整 桶数量。 rehash 函数被调用时&#xff0c;需要注意以下几点&#xff1a; rehash 函数可能会造成 unordered_map 的迭代器失效。如果我们在重新哈希后仍需要继续迭代 unordered_…

机器学习实战六步法之数据预处理(五)

要落地一个机器学习的项目&#xff0c;是有章可循的&#xff0c;通过这六个步骤&#xff0c;小白也能搞定机器学习。 看我闪电六连鞭&#xff01;&#x1f923; 数据的预处理通常包括 5 个步骤&#xff0c;如下&#xff1a;这个是比较完整的一个步骤&#xff0c;不同的算法可能…

内网隧道代理技术(一)之内网隧道代理概述

内网隧道代理技术 内网转发 在渗透测试中&#xff0c;当我们获得了外网服务器&#xff08;如web服务器&#xff0c;ftp服务器&#xff0c;mali服务器等等&#xff09;的一定权限后发现这台服务器可以直接或者间接的访问内网。此时渗透测试进入后渗透阶段&#xff0c;一般情况…

FreeRTOS(8)----任务通知

一&#xff0c;任务通知的简介 相对于之前的信号量&#xff0c;事件组等&#xff0c;所谓的任务通知核心就是一个32位的无符号整数和8位的通知状态 任务通知可以通过如下方法更新接收任务的通知值&#xff1a; ● 不覆盖接收任务的通知值 ( 如果上次发送给接收任务的通知还没…

MyBatisPlus总结(1.0)

MyBatis-Plus MyBatis-Plus介绍 MyBatis-Plus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生 特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影…

为何波卡被称为Layer 0?

理解区块链的技术本质&#xff0c;将揭示加密货币运行轨迹的神秘面纱。了解这背后的原理&#xff0c;将为你带来全新的视角&#xff0c;让你对加密货币的奇妙世界充满无尽的好奇。 波卡是一个内部互连的区块链平台&#xff0c;被赋予技术堆栈元协议或Layer 0的定义&#xff0c…

Golang 基础案例集合:中文拼音转换、解析二维码、压缩 zip、执行定时任务

前言 曾经&#xff0c;因为不够注重基础吃了好多亏。总是很喜欢去看那些高大上的东西&#xff0c;却忽略了最基本的东西。然后会错误的以为自己懂的很多&#xff0c;但是其实是沙堆中筑高台&#xff0c;知道很多高大上的架构&#xff0c;但是基础的东西却不太了解。我觉得&…

PySpark实战指南:大数据处理与分析的终极指南【上进小菜猪大数据】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 大数据处理与分析是当今信息时代的核心任务之一。本文将介绍如何使用PySpark&#xff08;Python的Spark API&#xff09;进行大数据处理和分析的实战技术。我们将探讨PySpark的基本…

P2[1-2]STM32简介(stm32简介+ARM介绍+片上外设+命名规则+系统结构+引脚定义+启动配置+最小系统电路+实物图介绍)

1.1 stm32简介 解释:ARM是核心部分,程序的内核,加减乘除的计算,都是在ARM内完成。 智能车方向:循迹小车,读取光电传感器或者摄像头数据,驱动电机前进和转弯。 无人机:用STM32读取陀螺仪加速度计的姿态数据,根据控制算法控制电机的速度,从而保证飞机稳定飞行。 机…

maven的pom文件

maven项目中会有pom文件&#xff0c; 当新建项目时候&#xff0c; 需要添加我们需要的依赖包。所以整理了一份比较常用的依赖包的pom&#xff0c;方便以后新建项目或者添加依赖包时copy且快捷。不需要的依赖可以删掉&#xff0c;避免首次远程拉取失败和缩小项目打包大小。 <…