【从零开始学习JAVA | 第四十五篇】动态代理

news2025/1/16 4:55:03

目录

前言:

动态代理:

动态代理实现步骤:

动态代理的应用场景:

 总结:


前言:

动态代理作为一种强大的编程技术,不仅为我们提供了灵活性和可扩展性,还为软件开发和系统设计带来了许多优势。通过动态代理,我们能够在运行时创建和修改对象,实现无需修改现有代码的功能增强和拦截操作。

例如我们想为一个类添加新的成员方法,以往我们使用的就是直接往类里面进行添加,我们把这种方法叫做侵入式添加,而这种添加在代码体积大的时候,可能会引起想不到的错误,因此我们引出了动态代理这个概念,而动态代理可以非侵入式的给代码增加额外的功能

动态代理:

动态代理是一种编程技术,它允许在运行时创建代理对象并将方法调用转发给真实的目标对象。动态代理可以用于对对象的方法进行拦截、增强或修改,而无需修改原始对象的代码基于反射机制,在运行时动态地生成代理类,从而实现对目标对象的间接访问。

动态代理常用于解耦和增强系统的功能。通过代理,我们可以在不修改现有代码的情况下,为对象添加额外的行为,如性能监控、日志记录、事务管理等。它还能够简化系统架构,提升代码的可维护性和可测试性。

动态代理在Java中有多种实现方式,如基于Java的Proxy类和基于字节码操作的第三方库,如CGLIB和Byte Buddy。无论哪种方式,动态代理都为开发人员提供了一种灵活且强大的工具,使得面向对象编程更加灵活和可扩展。

动态代理实现步骤:

  1. 定义目标接口:创建一个接口,定义需要代理的方法。

  2. 创建目标类:实现目标接口的具体类,即实际执行操作的类。

  3. 实现 InvocationHandler 接口:创建一个实现 java.lang.reflect.InvocationHandler 接口的代理处理类。这个类将实现方法调用的逻辑。

  4. 使用 Proxy 类创建代理对象:通过 java.lang.reflect.Proxy 的 newProxyInstance() 方法,创建代理对象。该方法接受三个参数:类加载器、目标接口数组和代理处理实现。

  5. 调用代理对象的方法:通过代理对象调用目标接口中的方法,代理处理类中的 invoke() 方法会被触发执行。可以在该方法中添加额外的逻辑来增强目标方法的行为。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 步骤 1: 定义目标接口
public interface Hello {
    void sayHello();
}

// 步骤 2: 创建目标类
class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello, world!");
    }
}

// 步骤 3: 实现 InvocationHandler 接口
class ProxyHandler implements InvocationHandler {
    private Object target;

    public ProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invocation");
        Object result = method.invoke(target, args);
        System.out.println("After method invocation");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        // 步骤 4: 使用 Proxy 类创建代理对象
        Hello hello = new HelloImpl();
        Hello proxy = (Hello) Proxy.newProxyInstance(
                        Hello.class.getClassLoader(),
                        new Class<?>[] { Hello.class },
                        new ProxyHandler(hello)
                );

        // 步骤 5: 调用代理对象的方法
        proxy.sayHello();
    }
}

动态代理的应用场景:

  1. 面向切面编程(AOP):动态代理可以用于在不修改目标类的情况下,为目标类的方法添加额外的逻辑,如日志记录、事务管理、性能监控等。

  2. 延迟加载(Lazy Loading):动态代理可以延迟加载对象的创建,当真正需要使用对象时再创建并执行相应的操作,可以提高系统性能和资源利用率。

  3. 缓存代理:动态代理可以用于在方法调用前检查缓存中是否存在结果,如果存在则直接返回缓存的结果,避免重复执行相同的操作,提高系统的响应速度。

  4. 权限控制:动态代理可以用于在方法调用前进行权限验证,判断用户是否有权限执行该方法,从而实现细粒度的权限控制。

  5. 远程代理:动态代理可以用于在网络通信中,通过代理对象将方法调用传递给远程的服务对象,实现远程方法调用(RPC)。

  6. 事件监听和消息分发:动态代理可以用于实现事件监听和消息分发机制,在触发某个事件或收到消息时,通过代理对象将事件或消息传递给注册的监听器进行处理。

 总结:

动态代理是一种在运行时生成代理对象的技术,它可以在不修改原有代码的情况下,对目标对象的方法进行增强或拦截。实现动态代理的步骤包括定义目标接口、创建目标类、实现 InvocationHandler 接口以及使用 Proxy 类创建代理对象。通过动态代理,我们可以在目标方法的前后添加额外逻辑,如日志记录、性能监测等。动态代理具有较高的灵活性和可扩展性,在实际开发中被广泛应用于日志框架、事务管理等场景。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

 

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

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

相关文章

在Linux虚拟机内配置nginx以及docker

目录 1、nginx源码包编译以及安装依赖 1、配置安装所需的编译环境 2、安装函数库&#xff08;pcre、zlib、openssl&#xff09; 2、安装nginx 1、获取源码包 2、解压编译 3、启动nginx服务 1、关闭防火墙 2、运行nginx 3、使用本地浏览器进行验证 3、安装docker 1、…

章节7:XSS检测和利用

章节7&#xff1a;XSS检测和利用 测试payload <script>alert(XSS)</script> <script>alert(document.cookie)</script> ><script>alert(document.cookie)</script> ><script>alert(document.cookie)</script> &qu…

【数据结构】“栈”的模拟实现

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

java线程的优先级、守护线程的概念

1.线程的调度 抢占式调度 非抢占式调度 1.1 抢占式调度 优先级越高&#xff0c;抢到cpu的概率越高 1.2 守护线程 守护线程&#xff0c;非守护线程。当其他的非守护线程执行完毕以后&#xff0c;守护线程会陆续结束。 守护线程的应用场景

SpringBoot06---前端路由VueRouter

单页面应用&#xff0c;意思是只有一个html&#xff0c;变化的内容是不同组件进行切换&#xff0c;每个组件加载网络请求&#xff0c;渲染对应的数据&#xff0c;这个内容就是学习怎么完成组件切换 以网易云音乐为例&#xff1a; 网易云音乐 (163.com) 现在无需注册&#xf…

力扣 377. 组合总和 Ⅳ

题目来源&#xff1a;https://leetcode.cn/problems/combination-sum-iv/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a; 本题求的是排列总和&#xff0c;而且仅仅是求排列总和的个数&#xff0c;并不是把所有的排列都列出来。动规五部曲分析如下&…

【STM32】FreeRTOS消息队列和信号量学习

一、消息队列&#xff08;queue&#xff09; 队列是一种用于实现任务与任务之间&#xff0c;任务与中断之间消息交流的机制。 注意&#xff1a;1.数据的操作是FIFO模式。 2.队列需要明确数据的大小和队列的长度。 3.写和读都会出现堵塞。 实验&#xff1a;创建一个消息队列…

keil下载程序具体过程:概述

一、前言 keil下载程序具体过程将由一系列的博客组成&#xff0c;将深入探讨keil这种IDE下载镜像文件时具体做了哪些事情。我们平常下载镜像的时候&#xff0c;只是点击了一下Download按钮&#xff0c;剩下的都由keil替代我们完成了。本系列博客将揭示这一过程&#xff0c;keil…

Dynamic Web TWAIN Crack,文档扫描SDK

Dynamic Web TWAIN Crack,文档扫描SDK Dynamic Web TWAIN用于快速部署 Web 应用程序的文档扫描 SDK&#xff0c;文档扫描SDK&#xff0c;&#xff0c;超过 5300 家公司信任 Dynamic Web TWAIN &#xff0c;因其稳健性和安全性而受到超过 5300 家公司的信赖&#xff0c;Dynamic …

大数据-玩转数据-Flink RedisSink

一、添加Redis Connector依赖 具体版本根据实际情况确定 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-redis_2.11</artifactId><version>1.1.5</version> </dependency>二、启动redis 参…

JVM 基础

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 JVM 类加载机制 JVM 类加载机制分为五个部分&#xff1a;加载&#xff0c;验证&#xff0c;准备&#xff0c;解析&#xff0c;初始化&am…

手把手带你跑通网站上线全流程(一个简单的HTML和Python服务端完整上线流程)

我将向你介绍如何将一个网站部署到公网&#xff0c;包含完整流程。 前端静态网站 静态网站文件 首先需要准备一个简单的网页文件用于展示页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&quo…

docker 安装elasticsearch、kibana

下载es镜像 docker pull elasticsearch 启动es容器 docker run --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -e ES_JAVA_OPTS"-Xms512m -Xmx512m" -d elasticsearch 验证es界面访问 ​​​​​http://节点ip:9200/ ​…

三.SpringBoot整合Elasticsearch

SpringBoot整合Elasticsearch 前言一.java调用es的方式和工具二.java集成Elasticsearch-Rest-Client1.引入pom2.导入版本不一致问题3.编写配置类4.测试类4.1 执行前4.2 执行后 5.其他篇章 前言 我们整合es直接给es发请求就可以了&#xff0c;但是现在有很多方式去调用es的接口…

为什么需要智能指针?

为什么需要智能指针&#xff1f; 解决忘记释放内存导致内存泄漏的问题。解决异常安全问题。 #include<iostream> using namespace std;int div() {int a, b;cin >> a >> b;if (b 0)throw invalid_argument("除0错误");return a / b; } void Func(…

入门指南 | 如何系统搭建自己的营销战略学习体系成为领域专家?

独自进入一个行业&#xff0c;如果你没有几年的行业经验或者独特的营销方式&#xff0c;很难在行业里站住脚&#xff08;每个行业潜规则都很多&#xff09;。 每个行业都有周期&#xff0c;都有很多竞争对手&#xff0c;你扎进去一个具体的行业&#xff0c;对于各种资源有限的自…

Mysql 和Oracle的区别

、mysql与oracle都是关系型数据库&#xff0c;Oracle是大型数据库&#xff0c;而MySQL是中小型数据库。但是MySQL是开源的&#xff0c;但是Oracle是收费的&#xff0c;而且比较贵。 1 2 mysql默认端口&#xff1a;3306&#xff0c;默认用户&#xff1a;root oracle默认端口&…

FileZilla Server安装配置使用说明

作者&#xff1a;John 链接&#xff1a;https://www.zhihu.com/question/20577011/answer/2360828234 来源&#xff1a;知乎 第一步&#xff1a;右键点击”立即下载“ 第二步&#xff1a;服务器端点击&#xff0c;“windows平台”版本 第三步&#xff1a;这个安装最新的“Fi…

时序预测 | Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 时序预测 | Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型 1.Matlab实现基于GRNN广义回归神经网络的电力负荷预测模型 2.单变量时间序列预测; 3.多指标评价,评价指标包括:R2、MAE、MBE等,代码质量极高…

由浅入深学习Tapable

文章目录 由浅入深学习TapableTapable是什么Tapable的Hook分类同步和异步的 使用Sync*同步类型钩子基本使用bailLoopWaterfall Async*异步类型钩子ParallelSeries 由浅入深学习Tapable webpack有两个非常重要的类&#xff1a;Compiler和Compilation。他们通过注入插件的方式&a…