Java中JDK动态代理

news2024/11/18 13:40:06

参考:疯狂Java讲义 第18章

文章目录

    • 前言
      • 复杂度与耦合的矛盾
    • 使用JDK动态代理
    • 总结

前言

复杂度与耦合的矛盾

开发实际应用的软件系统时,通常会存在相同代码段重复出现的情况,在这种情况下,一般都提取为一个方法,在不同的地方调用。
在这里插入图片描述
对于如图18.5所示的软件系统,如果需要修改深色部分的代码,则只要修改一个地方即可,而调用该方法的代码段,不管有多少个地方调用了该方法,都完全无须任何修改,只要被调用方法被修改了,所有调用该方法的地方就会自然改变——通过这种方式,大大降低了软件后期维护的复杂度。

但采用这种方式来实现代码复用依然产生一个重要问题:代码段1、代码段2、代码段3和深色代码段分离开了,但代码段1、代码段2和代码段3又和一个特定方法耦合了!最理想的效果是:代码段1、代码段2和代码段3既可以执行深色代码部分,又无须在程序中以硬编码方式直接调用深色代码的方法,这时就可以通过动态代理来达到这种效果。

使用JDK动态代理

下面是一个简单的JDK动态代理的例子

  1. 由于JDK动态代理只能为接口创建动态代理,所以下面先提供一个Dog接口。
public interface Dog {
	void info();
	void run();
}
  1. 为该Dog接口提供一个或多个实现类。此处先提供一个简单的实现类:GunDog
public class GunDog implements Dog {

	@Override
	public void info() {
		System.out.println("我是一只猎狗");
	}

	@Override
	public void run() {
		System.out.println("我快速奔跑");
	}

}

上面代码没有丝毫的特别之处,该Dog的实现类仅仅为每个方法提供了一个简单实现。再看需要实现的功能:让代码段1、代码段2和代码段3既可以执行深色代码部分,又无须在程序中以硬编码方式直接调用深色代码的方法。此处假设info()、run()两个方法代表代码段1、代码段2,那么要求:程序执行info()、run()方法时能调用某个通用方法,但又不想以硬编码方式调用该方法。下面提供一个DogUtil类,该类里包含两个通用方法。

  1. 提供公共调用的方法
public class DogUtil {
	//第一个拦截器方法
	public void method1() {
		System.out.println("==== 模拟第一个通用方法 ====");
	}
	//第一个拦截器方法
	public void method2() {
		System.out.println("==== 模拟第二个通用方法 ====");
	}
}

借助于 Proxy 和 InvocationHandler就 可 以 实 现—— 当 程 序 调用info() 方 法 和 run() 方 法 时 , 系 统 可 以 “ 自 动 ” 将 method1() 和method2()两个通用方法插入info()和run()方法中执行。
这个程序的关键在于下面的MyInvokationHandler类,该类是一个InvocationHandler实现类,该实现类的invoke()方法将会作为代理对象的方法实现。

  1. 新建 MyInvokationHandler 类,实现 InvoketionHandler 接口

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

public class MyInvocationHandler implements InvocationHandler {
	//需要被代理的对象
	private Object target;
	public void setTarget(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		DogUtil du = new DogUtil();
		du.method1();// 通用方法1
		// 使用反射,调用目标对象的原来的方法
		Object result = method.invoke(target, args);
		du.method2();// 通用方法2
		return result;
	}

}

  1. 新建一个 MyProxyFactory 类,用来创建动态代理类对象
public class MyProxyFactory {
	public static Object getProxy(Object target) throws Exception {
		// 创建一个 MyInvocationHandler 对象,并为其设置 target 目标类。
		MyInvocationHandler handler = new MyInvocationHandler();
		handler.setTarget(target);
		// 创建并返回一个动态代理对象
		Object proxyInstance = Proxy.newProxyInstance(
				ClassLoader.getSystemClassLoader()
				, target.getClass().getInterfaces()
				, handler);
		return proxyInstance;
		
	}
}
  1. 测试使用
public class TestDemo {

	public static void main(String[] args) throws Exception {
		Dog dog = new GunDog();
		// 根据目标类,获取动态代理对象
		Dog proxyDog = (Dog) MyProxyFactory.getProxy(dog);
		proxyDog.info();
		proxyDog.run();
	}
/*
==== 模拟第一个通用方法 ====
我是一只猎狗
==== 模拟第二个通用方法 ====
==== 模拟第一个通用方法 ====
我快速奔跑
==== 模拟第二个通用方法 ====
 */
}

总结

不难发现采用动态代理可以非常灵活地实现解耦。通常而言,使用Proxy生成一个动态代理时,往往并不会凭空产生一个动态代理,这样没有太大的实际意义。通常都是为指定的目标对象生成动态代理。
这种动态代理在AOP(Aspect Orient Programming,面向切面编程)中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理。
AOP代理包含的方法与目标对象包含的方法示意图如图:
在这里插入图片描述

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

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

相关文章

SOP企业内部推行:效率飙升100%,质量保障零瑕疵!

在企业的日常运营中,你是否经常遇到这样的问题:同样一项工作,不同的人做出来效果却大相径庭?或者,明明已经制定了工作流程,但执行起来却总是出现偏差,导致效率低下、质量不稳?这些问…

【STM32单片机_(HAL库)】3-2-2【中断EXTI】【电动车报警器项目】继电器定时开闭

1.硬件 STM32单片机最小系统继电器模块 2.软件 继电器模块alarm驱动文件添加GPIO常用函数main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "alarm.h"int main(void) {HAL_Init(); …

海外服务器和内地服务器有什么区别?

海外服务器和内地服务器在许多方面存在区别,主要包括以下几个方面: 1. 地理位置 海外服务器:位于中国大陆以外的地区,比如美国、欧洲、东南亚等地。常见的海外服务器提供商有Amazon Web Services(AWS)、Goo…

稚晖君发布5款全能人形机器人,开源创新,全能应用

8月18日,智元机器人举行“智元远征 商用启航” 2024年度新品发布会,智元联合创始人彭志辉主持并发布了“远征”与“灵犀”两大系列共五款商用人形机器人新品——远征A2、远征A2-W、远征A2-Max、灵犀X1及灵犀X1-W,并展示了在机器人动力、感知、…

【LLM之Base Model】Weaver论文阅读笔记

研究背景 当前的大型语言模型(LLM)如GPT-4等,尽管在普通文本生成中表现出色,但在创造性写作如小说、社交媒体内容等方面,往往不能很好地模仿人类的写作风格。这些模型在训练和对齐阶段,往往使用的是大规模…

Java | Leetcode Java题解之第347题前K个高频元素

题目&#xff1a; 题解&#xff1a; class Solution {public int[] topKFrequent(int[] nums, int k) {Map<Integer, Integer> occurrences new HashMap<Integer, Integer>();for (int num : nums) {occurrences.put(num, occurrences.getOrDefault(num, 0) 1);…

【layui】layer弹出图片层(开启图片旋转 放大 缩小 还原)

详细参照layui官网组件 弹出层组件 &#x1f525;Photots —————————————————————————— 弹出图片层&#xff08;开启图片旋转 放大 缩小 还原&#xff09;是layui2.8.16的新增功能&#xff0c; 新增 photos 层的鼠标滚轮缩放功能 是layui2.8.16的新增…

8.17模拟赛题解

先考虑空间能不能把N个座位放好 最优的方式就是挨着摆放 那么一排能摆放QL/x的商个椅子 &#xff0c;然后计算摆放完N个座位需要多少排&#xff0c;N/Q 向上取整 计算所需要的排总共占据多宽&#xff0c;讨论有没有超过W&#xff0c;然后讨论剩余空间还能放几条走廊 如果走廊数…

蚓链数字化营销:连接心灵的新桥梁

在当今数字化浪潮汹涌的时代&#xff0c;营销领域也经历了一场深刻的变革。蚓链数字化营销&#xff0c;已不仅仅是一种推广手段&#xff0c;更是连接品牌与消费者心灵的新桥梁&#xff0c;让每一次互动都充满温度与价值。 曾经&#xff0c;品牌与消费者之间的沟通隔着一层厚厚…

小白零基础学数学建模系列-Day8-多目标规划问题与案例实践

文章目录 1. 引言1.1 优化问题的背景1.2 单目标规划与多目标规划的概述 2. 单目标规划2.1 定义2.2 应用场景2.3 求解方法2.4 案例&#xff1a;制造企业生产成本最小化的优化方案2.4.1 案例背景2.4.2 模型建立2.4.3 模型求解2.4.4 结果分析2.4.5 总结 3. 多目标规划3.1 定义3.2 …

【MySQL进阶之路】数据库的操作

目录 创建数据库 字符集和校验规则 查看数据库支持的字符集 查看数据库支持的字符集校验规则 指定字符集和校验规则 在配置文件中配置 查看数据库 显示创建语句 修改数据库 删除数据库 数据库的备份和恢复 备份整个数据库 备份特定表 备份多个数据库 备份所有数据…

无人机测绘技术及应前景详解

无人机测绘技术是一种将无人机技术、遥感技术、地理信息系统&#xff08;GIS&#xff09;和计算机技术相结合&#xff0c;对自然地理要素或地表人工设施的形状、大小、空间位置及其属性等进行测定、采集并绘制成图的技术。它利用高精度传感器&#xff08;如激光雷达、航拍相机等…

遗传进化算法进行高效特征选择

在构建机器学习模型时&#xff0c;特征选择是一个关键的预处理步骤。使用全部特征往往会导致过拟合、增加计算复杂度等问题。因此&#xff0c;我们需要从原始特征集中选择一个最优子集&#xff0c;以提高模型的泛化性能和效率。 特征选择的目标是找到一个二元掩码向量&#xf…

液相色谱仪仪器校准怎么做?具体校准方法是什么?

液相色谱法概述 液相色谱仪是由输液系统、进样系统、分离系统、检测系统和数据处理系统等部分组成的分析仪器。液相色谱仪是根据样品之中各组分在色谱柱中的固定相和流动相间的分布或吸附特性的差异&#xff0c;流动相将样品带入色谱柱进行分离。由检测器检测&#xff0c;并由…

Java 和 .NET Core 在企业级应用开发中各有什么优势和劣势?看看AI是怎么回答的

Java 和 .NET Core 在企业级应用开发中各有什么优势和劣势&#xff1f;看看AI是怎么回答的 1.kimi 网址&#xff1a;https://kimi.moonshot.cn/ Kimi是北京月之暗面科技有限公司于2023年10月9日推出的一款智能助手&#xff0c;主要应用场景为专业学术论文的翻译和理解、辅助分析…

python基础语法 010 类和对象-6-1 继承定义

前提&#xff1a; 在真实世界中&#xff0c;类型之间可能存在范围包含关系&#xff0c;比如&#xff1a;人这个类型和亚洲人这个类型。 人是包括了亚洲人的&#xff0c;如果某人是员工亚洲人&#xff0c;那么它必定是一个人 这种关系&#xff0c;在编程语言中称为继承关系 比如…

Java Web|day5.MyBatis

MyBatis 定义 它是一款半自动的ORM持久层框架&#xff0c;具有较高的SQL灵活性&#xff0c;支持高级映射(一对一&#xff0c;一对多)&#xff0c;动态SQL&#xff0c;延迟加载和缓存等特性&#xff0c;但它的数据库无关性较低 **ORM: **Object Relation Mapping&#xff0c;…

数据库调优的流程及参考参数

1.数据库调优的流程&#xff1a; 1.1.调优思考流程&#xff1a; 1.对数据库进行调优的时候&#xff0c;我们可以依据以下步骤进行思考&#xff1a; 整个流程划分成了观察 (Show status) 和行动 (Action) 两个部分。字母 S 的部分代表观察&#xff08;会使用相应的分析工具&am…

全自由度控制八极电磁铁-吴贤铭智能工程学院案例

根据客户需求&#xff0c;上海天端实业有限公司设计八极电磁铁方案 八极电磁铁产品说明 八极电磁铁可在空间内部产生方向及强度可控的均匀磁场或梯度磁场&#xff0c;八组磁极以空间极轴布置&#xff0c;每组磁极可独立控制&#xff0c;磁场空间300mm直径球域。 八极电磁铁电…

electron 官网速通

前言&#xff1a;参考Electron 中文网。 核心知识点&#xff1a;有哪些进程&#xff0c;进程之间的通信&#xff0c;electron API 分类及怎么调用。 一、快速开始 1. 新建一个 my-electron 的文件夹。 2. 运行 npm init 创建 package.json 文件。 3. 填写 author 和 descr…