当前位置: 首页 > news >正文

都2024年了,还有人不懂动态代理么?

文章目录

  • 一、定义
  • 二、静态代理
  • 三、动态代理
    • 1. JDK代理
      • 1.1 JDK代理实现流程
      • 1.2 动态生成的类字节码
    • 2. Cglib代理
      • 2.1 Cglib实现流程
  • 四、总结

一、定义

静态代理和动态代理都反映了一个代理模式,代理模式是一种经典的设计模式,常用于为其他对象提供一种代理或占位符,以限制对它的访问,充当访问对象的中介
就好比平时我们租房,会和中介进行沟通,中介带我们去看房,中介又与房东保持联系,但房东不会带我们看房。


二、静态代理

静态代理是一种代理模式的实现,静态代理在编译时就确定了代理类和目标类之间的关系。
在静态代理中,代理类和目标类通常实现相同的接口,或者代理类继承目标类。
代理类作为目标类的包装,持有目标类的引用,并且调用目标对象的方法前后进行增强操作。
下面举个例子

public interface Landlord {/*** 出租房间*/void rentingHouse();}
public class ShenZhenLandlord implements  Landlord {@Overridepublic void rentingHouse() {System.out.println("深圳房东出租房间");}
}
public class Intermediary implements Landlord{/*** 代理类*/private final Landlord landlord;public Intermediary(Landlord landlord) {this.landlord = landlord;}@Overridepublic void rentingHouse() {System.out.println("中介带租客看房");landlord.rentingHouse();System.out.println("中介收取出租非");}
}
public static void main(String[] args) {// 目标类Landlord landlord = new ShenZhenLandlord();//代理类Intermediary intermediary = new Intermediary(landlord);// 运行代理方法intermediary.rentingHouse();
}

image-20240623131158278

这是一个经典的代理模式的实现,可以在不修改原对象的情况下对目标类进行增强处理,但是若接口新增方法,所有代理类都都需要新增对应的实现,不好维护。


三、动态代理

动态代理是一个在运行期间动态创建代理对象的技术,它允许开发者为一个或多个接口创建一个代理对象,且无需事先知道具体实现类。

静态代理和动态代理的区别在于class文件是编译期间确定还是运行期间确定
静态代理在编写代码的时候就明确了代理类和目标类之间的关系,在编译阶段会生成一个Class对象。
动态代理则是在运行阶段动态生成代理对象,在运行的时候动态生成字节码,并加载到JVM中去


1. JDK代理

JDK代理技术是Java提供的一种动态代理技术,使用方式如下

public class ProxyFactory {/*** 目标类*/private Object target;public ProxyFactory(Object target) {this.target = target;}public Object getProxyInstance() {return Proxy.newProxyInstance(// 目标类加载器target.getClass().getClassLoader(),// 目标对象的接口类型target.getClass().getInterfaces(),// 事件处理new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前置增强");method.invoke(target, args);System.out.println("后置增强");return null;}});}
}
public static void main(String[] args) {ShenZhenLandlord landlord = new ShenZhenLandlord();System.out.println(landlord.getClass());Landlord proxyInstance = (Landlord) new ProxyFactory(landlord).getProxyInstance();proxyInstance.rentingHouse();System.out.println(proxyInstance.getClass());
}

image-20240623131414977

代理类打印出的Class为com.sun.proxy.$Proxy0, 从ShenZhenLandlord到 com.sun.proxy.$Proxy0 ,其中经历了什么呢?


1.1 JDK代理实现流程

需要知道的是JVM虚拟机的类加载过程分为加载、验证、准备、解析、初始化这五个阶段, 在加载阶段需要进行下面这几个步骤:

  1. 通过一个类的全限定名获取定义此类的二进制字节流
  2. 将这个字节流所代表的静态结构转化为方法区的运行时数据结构
  3. 内存生成一个代表这类的Class对象,作为方法区这个类的各种数据访问入口

而获取类的二进制字节流,JVM提供了三种途径:

  1. 本地获取字节码,比如前面的ShenZhenLandlord类,编译后就属于本地的字节码
  2. 从网络中获取,可以使用URLClassLoader来加载类
  3. 运行时计算生成,在程序运行的过程中动态生成类字节码

而代理就是运行时动态生成字节码,然后交给JVM进行类加载过程使用。
所以经过JDK代理后,从ShenZhenLandlord变成了com.sun.proxy.$Proxy0,也就是程序在运行中通过计算,生成了$Proxy0代理类的类字节码。


1.2 动态生成的类字节码

由于动态生成的类字节码是动态计算出来并加载到JVM内存中去,因此无法通过查看编译后的文件去查看这个代理类的 Class文件。
不过,可以通过arthas工具来查看动态生成的类字节码。
下载官网:https://arthas.aliyun.com/doc/download.html#%E7%94%A8-arthas-boot-%E5%90%AF%E5%8A%A8
输入命令java -jar arthas-boot.jar 运行arthas

image-20240623131648385

proxy.jdk.Main 就是我们要查看的目标类,按3进入监控界面,如下图所示就代表进入成功了

img

输入命令jad com.sun.proxy.$Proxy0命令,就能解析出$Proxy0的源码了

img

整理一下代码,如下:

public final class $Proxy0
extends Proxy
implements Landlord {private static Method m1;private static Method m3;private static Method m2;private static Method m0;// 构造参数为InvocationHandlerpublic $Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);}static {try {m3 = Class.forName("proxy.static_proxy.Landlord").getMethod("rentingHouse", new Class[0]);return;}catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());}catch (ClassNotFoundException classNotFoundException) {throw new NoClassDefFoundError(classNotFoundException.getMessage());}}// Landlord接口的`rentingHouse`方法public final void rentingHouse() {try {this.h.invoke(this, m3, null);return;}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}
}

看一个类,首先先看构造方法,KaTeX parse error: Expected 'EOF', got '#' at position 70: …就是`ProxyFactory#̲getProxyInstanc…Proxy0`的构造方法传进去的,也就是是同一个!!

    public Object getProxyInstance() {return Proxy.newProxyInstance(// 目标类加载器target.getClass().getClassLoader(),// 目标对象的接口类型target.getClass().getInterfaces(),// 事件处理new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前置增强");method.invoke(target, args);System.out.println("后置增强");return null;}});}

我们稍微看一下Proxy的源码

private static final Class<?>[] constructorParams ={ InvocationHandler.class };public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
throws IllegalArgumentException
{final Class<?>[] intfs = interfaces.clone();/** 获取动态生成的字节码*/Class<?> cl = getProxyClass0(loader, intfs);/** 获取这个代理类的构造参数为InvocationHandler的构造方法*/final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}// 将h作为构造参数创建代理类return cons.newInstance(new Object[]{h});
}

那么在$Proxy0#rentingHouse方法调用了构造参数传进来的InvocationHandlerinvoke方法,也就是调用了下面这个方法(增强后的方法)

new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前置增强");method.invoke(target, args);System.out.println("后置增强");return null;}
}

通过这,就可以得出下面的结论:

  1. 代理类实际上就是实现了Landlord接口,重写了rentingHouse方法
  2. 当外界调用代理类的rentingHouse方法的时候,实际上就是调用了new InvocationHandler的invoke方法

2. Cglib代理

Cglib(Code Generation Library)是一个强大的高性能代码生成库,用于在运行时扩展Java类和实现接口。它通过字节码技术动态生成新的类,从而实现对目标类的代理。Cglib代理是AOP(面向切面编程)中常用的一种代理方式,尤其是在需要代理那些没有实现接口的类时。
举个例子:
目标类如下

public class UserServiceImpl {public String selectList(){System.out.println("正在查询");return "小明, 小红, 小黄";}
}
public class UserLogProxy implements MethodInterceptor {/*** 生成 CGLIB 动态代理类方法** @param target* @return*/public Object getLogProxy(Object target) {// 增强器类,用来创建动态代理类Enhancer enhancer = new Enhancer();// 设置代理类的父类字节码对象enhancer.setSuperclass(target.getClass());// 设置回调enhancer.setCallback(this);// 创建动态代理对象并返回return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("开始查询");// 执行原始方法Object result = methodProxy.invokeSuper(o, objects);System.out.println("查询完毕");return result;}
}public class MethodProxy{public Object invokeSuper(Object obj, Object[] args) throws Throwable {try {init();FastClassInfo fci = fastClassInfo;return fci.f2.invoke(fci.i2, obj, args);} catch (InvocationTargetException e) {throw e.getTargetException();}}
}
public class Main {public static void main(String[] args) {// 目标对象UserServiceImpl userService = new UserServiceImpl();System.out.println(userService.getClass());// 代理对象UserServiceImpl proxy = (UserServiceImpl) new UserLogProxy().getLogProxy(userService);System.out.println(proxy.getClass());String userList = proxy.selectList();System.out.println(userList);while (true) {}}
}

image.png


2.1 Cglib实现流程

使用arthas工具,将proxy.cglib.UserServiceImpl$$EnhancerByCGLIB$$b96d19a3类的代码获取出来。

public class UserServiceImpl$$EnhancerByCGLIB$$b96d19a3
extends UserServiceImpl
implements Factory {private MethodInterceptor CGLIB$CALLBACK_0;public final String selectList() {// 是否设置了回调MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {UserServiceImpl$$EnhancerByCGLIB$$b96d19a3.CGLIB$BIND_CALLBACKS(this);methodInterceptor = this.CGLIB$CALLBACK_0;}// 设置回调,需要调用 intercept 方法if (methodInterceptor != null) {return (String)methodInterceptor.intercept(this, CGLIB$selectList$0$Method, CGLIB$emptyArgs, CGLIB$selectList$0$Proxy);}// 无回调,调用父类的 findUserList 即可return super.selectList();}}

在JVM编译阶段,Enhancer会根据目标类信息去动态生成代理类并设置回调。
当用户通过Cglib动态代理执行selectList方法的时候,会直接调用methodInterceptor.intercept方法,在intercept方法中通过invikeSuper调用父类的selectList方法。
如果没有设置回调,则直接调用父类的selectList方法。


四、总结

JDK代理与Cglib代理对比

  1. Cglib实现的动态代理是基于ASM字节码生成框架实现的,使用字节码技术生成代理类,在JDK1.6之前比使用Java反射效率要高一点。但是需要注意,Cglib代理技术不可对final类进行类或方法的代理,因为Cglib的原理是动态生成代理类的子类实现的。
  2. 在JDK1.6以后的版本已经开始对JDK代理进行优化(具体优化了什么 以后有机会再写篇文章讲),在调用次数较少的情况,JDK代理的效率要比Cglib代理效率要高,只有进行大量调用的时候,Cglib的优势才会出现。而到了JDK1.8,JDK代理的效率已经高于Cglib代理,因此在有接口的情况下推荐优先使用JDK代理,没接口优先推荐使用Cglib代理技术。

动态代理与静态代理的比较

  1. 动态代理的最大优势就是在于可以把接口中声明的所有方法转移到调用处理器的一个集中的方法进行处理(Invocation.invoke),在接口数量比较多的情况下,可以进行灵活处理。
  2. 如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题

相关文章:

都2024年了,还有人不懂动态代理么?

文章目录 一、定义二、静态代理三、动态代理1. JDK代理1.1 JDK代理实现流程1.2 动态生成的类字节码 2. Cglib代理2.1 Cglib实现流程 四、总结 一、定义 静态代理和动态代理都反映了一个代理模式&#xff0c;代理模式是一种经典的设计模式&#xff0c;常用于为其他对象提供一种…...

ARM功耗管理框架之PPU

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理框架&#xff1f;SCP&#xff1f;PPU&#xff1f;LPI&#xff1f;之间的关系&#xff1f;如何配合&#xff1f; 目录 一、功耗管理框架中的PPU 二、PPU的结构与连接关系 三、PPU操作模式和电源模式及其之间的转…...

说说 SSL 的错误认识和不足之处

最近明月在学习折腾 LNMP 期间无意中建了一个 Typecho 的博客小站&#xff0c;近一周的折腾下来&#xff0c;收获真的不少&#xff0c;致使兴趣也越来越浓了&#xff0c;在升级 LNMP 的时候捎带手的给这个 Typecho 博客也启用了 SSL。并且开启了 memcached 和 OPcache 优化加速…...

Go语言day1

下载go语言的安装程序&#xff1a; All releases - The Go Programming Language 配置go语言的环境变量&#xff1a; 写第一个go语言 在E:\go_workspace当前窗口使用cmd命令: 输入 go run test.go...

【Python机器学习】利用t-SNE进行流形学习

虽然PCA通常是用于变换数据的首选方法&#xff0c;使你能够用散点图将其可视化&#xff0c;但这一方法的性质限制了其有效性。 有一类用于可视化的算法叫做流形学习算法&#xff0c;它允许进行更复杂的映射&#xff0c;通常也可以给出更好的可视化。其中特别有用的一个就是t-S…...

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系(m_coord)

03 - matlab m_map地学绘图工具基础函数 - 设置坐标系&#xff08;m_coord&#xff09; 0. 引言1. m_proj使用方法2. 结语 0. 引言 上一篇介绍了m_proj函数用于初始化投影&#xff0c;本篇介绍的函数m_coord用于初始化地理坐标系或地磁坐标系&#xff0c;地理/地磁坐标系和投影…...

UEC++ 虚幻5第三人称射击游戏(一)

UEC 虚幻5第三人称射击游戏&#xff08;一&#xff09; 创建一个空白的C工程 人物角色基本移动 创建一个Character类添加一些虚幻商城中的基础动画 给角色类添加Camera与SPringArm组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category "SpringArm")clas…...

java小代码(1)

代码 &#xff1a; 今日总结到此结束&#xff0c;拜拜&#xff01;...

SLAM ORB-SLAM2(27)词袋模型

SLAM ORB-SLAM2(27)词袋模型 1. 词袋模型1.1. 词汇树1.2. 逆向索引表1.3. 逆向索引表2. 词袋向量3. 匹配候选帧3.1. 找出和当前帧具有公共单词的所有关键帧3.2. 找出和当前帧最多公共单词的关键帧3.3. 剔除共享单词数较少的关键帧3.4. 计算关键帧的共视关键帧组的总得分3.5. …...

OpenAI 的 GPT-5:CTO米拉-穆拉提说,到 2026 年将实现博士级智能(Ph.D.-Level))

据首席技术官米拉-穆拉提&#xff08;Mira Murati&#xff09;介绍&#xff0c;GPT-5 是 OpenAI 人工智能的下一代进化产品&#xff0c;将于 2025 年底或 2026 年初在特定任务中实现博士级智能。 GPT-5 内部代号为 "Gobi "和 “Arrakis”&#xff0c;将是一个多模态…...

macbook配置adb环境和用adb操作安卓手机

&#xff08;参考&#xff1a;ADB工具包的安装与使用_adb工具箱-CSDN博客&#xff09; 第一步&#xff1a;从Android开发者网站下载Android SDK&#xff08;软件开发工具包&#xff09;。下载地址为&#xff1a; 第二步&#xff1a;解压下载的SDK压缩文件到某个目录中。 进入解…...

微软TTS最新模型,发布9种更真实的AI语音

很高兴与大家分享 Azure AI 语音翻译产品套件的两个重大更新&#xff1a; 视频翻译和增强的实时语音翻译 API。 视频翻译&#xff08;批量&#xff09; 今天&#xff0c;我们宣布推出视频翻译预览版&#xff0c;这是一项突破性的服务&#xff0c;旨在改变企业本地化视频内容…...

python爬虫 -爬取 json 格式数据

在Python中&#xff0c;爬取JSON格式的数据通常涉及到发送 HTTP请求到某个URL&#xff0c;并解析返回的JSON数据。以下是一个简单的示例&#xff0c;说明如何使用Python的requests库来爬取JSON格式的数据&#xff1a; 1. 首先&#xff0c;确保你已经安装了requests库。如果没…...

Pytorch(5)-----梯度计算

一、问题 如何使用Pytorch计算样本张量的基本梯度呢&#xff1f;考虑一个样本数据集&#xff0c;且有两个展示变量&#xff0c;在给定初始权重的基础上&#xff0c;如何在每次迭代中计算梯度呢&#xff1f; 二、如何运行 假设有x_data 和 y_data 列表&#xff0c;计算两个列表需…...

C#的膨胀之路:创新还是灭亡

开篇概述 C#&#xff0c;这门由微软推出的编程语言&#xff0c;自2000年诞生以来&#xff0c;以其简洁的语法、强大的功能和广泛的应用场景&#xff0c;赢得了我等程序员的热爱。它在.NET框架的加持下&#xff0c;展现出无与伦比的开发效率和性能。然而&#xff0c;随着时间的流…...

SpringBoot 过滤器和拦截器的区别

SpringBoot 过滤器和拦截器的区别 Spring拦截器&#xff08;Interceptor&#xff09;和过滤器&#xff08;Filter&#xff09;是Spring框架中用于处理请求的两种机制&#xff0c;虽然它们都可以在请求处理的不同阶段进行拦截和处理&#xff0c;但它们的工作原理和应用场景有所…...

协程执行顺序引发的问题

引言 在Golang中&#xff0c;因为协程执行的顺序是不固定的&#xff0c;如果不在代码里进行控制&#xff0c;可能就会导致预期外的输出。 本文通过分析一段代码的执行来介绍这种情况&#xff0c;以及可行的控制协程执行顺序的方法&#xff1a; sleep()waitGroup 实例分析 代…...

android webview调用js滚动到指定位置

一、activity import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.tencent.smtt.sdk.WebView import com.tencent.smtt.sdk.WebViewClientclass MainActivity : AppCompatActivity() {private lateinit var webView: WebViewoverride fun …...

WPF 深入理解一、基础知识介绍

基础知识 本系列文章是对个人 B站 up 微软系列技术教程 记录 视频地址 https://www.bilibili.com/video/BV1HC4y1b76v/?spm_id_from333.999.0.0&vd_source0748f94a553c71a2b0125078697617e3 winform 与 wpf 异同 1.winform 项目结构 编辑主要是在 Form1.cs(页面)&#…...

腾讯云点播ugc upload | lack signature 问题处理

我犯一个很傻的错误 参考腾讯云官方文档&#xff1a;云点播 Web 端上传 SDK-开发指南-文档中心-腾讯云 进行开发&#xff0c;但是却报错了&#xff0c;始终找不到问题&#xff0c;错误提示&#xff1a;ugc upload | lack signature&#xff0c;意思是缺少签名或者签名失败&…...

计算机视觉实验二:基于支持向量机和随机森林的分类(Part one: 编程实现基于支持向量机的人脸识别分类 )

目录 一、实验内容 二、实验目的 三、实验步骤 四、实验结果截图 五、实验完整代码 六、报错及解决方案 PS:实验的运行速度受电脑性能影响,如遇运行卡顿请耐心等待。 一、实验内容 编程实现基于支持向量机的人脸识别分类,基本功能包括:Labeled Faces in th…...

5.什么是C语言

什么是 C 语言? C语言是一种用于和计算机交流的高级语言, 它既具有高级语言的特点&#xff0c;又具有汇编语言的特点 非常接近自然语言程序的执行效率非常高 C语言是所有编程语言中的经典&#xff0c;很多高级语言都是从C语言中衍生出来的&#xff0c; 例如:C、C#、Object-C、…...

DINO-DETR

DINO-DETR DETR收敛慢的问题1. Contrastive DeNoising Training(对比方法降噪训练)2. Mixed Query Selection(混合查询选择方法对锚点进行初始化)3. Look Forward Twice(两次前向方法)==DINO模型的传播过程,以及部分模块的改进==DETR收敛慢的问题 PnP-DETR(ICCV 2021) 改进了…...

Representation RL:HarmonyDream: Task Harmonization Inside World Models

ICML2024 paper code Intro 基于状态表征的model-based强化学习方法一般需要学习状态转移模型以及奖励模型。现有方法都是将二者联合训练但普遍缺乏对如何平衡二者之间的比重进行研究。本文提出的HarmonyDream便是通过自动调整损失系数来维持任务间的和谐&#xff0c;即在世界…...

Centos7系统下Docker的安装与配置

文章目录 前言下载Docker安装yum库安装Docker启动和校验配置Docker镜像加速卸载Docker 前言 此博客的内容的为自己的学习笔记&#xff0c;如果需要更具体的内容&#xff0c;可查看Docker官网文档内容 注意&#xff1a;以下命令在root管理员用户下运行&#xff0c;如果在普通用…...

无人机校企合作

有没有想过&#xff0c;无人机和校企合作能碰撞出怎样的火花&#xff1f;&#x1f525;今天就来给大家揭秘一下这个神秘组合&#xff01; 无人机&#xff0c;作为现代科技的代表&#xff0c;已经渗透到我们生活的方方面面。而校企合作&#xff0c;更是推动科技创新、培养人才的…...

八爪鱼现金流-028,个人网站访问数据统计分析,解决方案

个人网站访问数据统计分析&#xff0c;解决方案 调研 结论&#xff1a;使用百度统计 步骤 1.注册百度统计 2.获取安装代码 3.在项目中&#xff0c;页面代码添加如下片段 <script>var _hmt _hmt || [];(function() {var hm document.createElement("script&…...

大厂面试官问我:布隆过滤器有不能扩容和删除的缺陷,有没有可以替代的数据结构呢?【后端八股文二:布隆过滤器八股文合集】

往期内容&#xff1a; 面试官问我&#xff1a;Redis处理点赞&#xff0c;如果瞬时涌入大量用户点赞&#xff08;千万级&#xff09;&#xff0c;应当如何进行处理&#xff1f;【后端八股文&#xff08;1&#xff09;】-CSDN博客 本文为【布隆过滤器八股文合集】初版&#xff0c…...

PHP米表域名出售管理源码带后台

源码介绍 html5米表源码PHP域名销售程序安装方法&#xff1a; 本站已测试,各项功能正常,功能易用,不复杂,非常适合个人米表使用 1、所有文件传至网站目录 2、浏览器执行http://你的访问网址/install 3、输入mysql帐号及密码信息&#xff0c;提交安装 源码截图 源码下载 …...

【开发12年码农教你】Android端简单易用的SPI框架-——-SPA

Service(priority 1) public class APrinterService implements IPrinterService { Override public void print() { System.out.println(“this is a printer service.”); } } 复制代码 B模块 —— BPrinterService Service(path“b_printer”, priority 2) public class…...

以太坊==MetaMask获取测试币最新网址

估算分数https://community.infura.io/t/unable-to-receive-sepolia-eth-from-faucet/7715 Gitcoin Passport 水龙头地址&#xff0c;填入自己的测试地址 水龙头项目地址 GitHub - pk910/PoWFaucet: Modularized faucet for EVM chains with different protection methods (…...

军用FPGA软件 Verilog语言的编码准测之触发器、锁存器

军用FPGA软件 Verilog语言的编码准测之触发器、锁存器 语言 &#xff1a;Verilg HDL EDA工具&#xff1a;ISE、Vivado、Quartus II 军用FPGA软件 Verilog语言的编码准测之触发器、锁存器一、引言二、基本编程规范之触发器强制准则1---禁止在同一个 always 语句中混合使用有复位…...

智能汽车 UI 风格独具魅力

智能汽车 UI 风格独具魅力...

javafx例子笔记

文章目录 创建过程javafx独立版报错 Exception in thread "WindowsNativeRunloopThread" java.lang.NoSuchMethodError: <init> javafx是java gui工具。 一般会转换为exe&#xff0c;成为可交互的应用。 那么来个简单的例子吧。 先说明一点&#xff0c;javafx不…...

【ajax基础】回调函数地狱

一&#xff1a;什么是回调函数地狱 在一个回调函数中嵌套另一个回调函数&#xff08;甚至一直嵌套下去&#xff09;&#xff0c;形成回调函数地狱 回调函数地狱存在问题&#xff1a; 可读性差异常捕获严重耦合性严重 // 1. 获取默认第一个省份的名字axios({url: http://hmaj…...

SparkSQL的分布式执行引擎-Thrift服务:学习总结(第七天)

系列文章目录 SparkSQL的分布式执行引擎 1、启动Thrift服务 2、beeline连接Thrift服务 3、开发工具连接Thrift服务 4、控制台编写SQL代码 文章目录 系列文章目录前言一、SparkSQL的分布式执行引擎(了解)1、启动Thrift服务2、beeline连接Thrift服务3、开发工具连接Thrift服务4、…...

联华集团:IT团队如何实现从成本中心提升至价值中心|OceanBase 《DB大咖说》(十)

OceanBase《DB大咖说》第 10 期&#xff0c;我们邀请到了联华集团的CTO楼杰&#xff0c;来分享他如何思考 IT 业务价值&#xff0c;以及联华华商数据库的升级实践。 楼杰从大学毕业后就进入了联华工作&#xff0c;并一直扎根在近 20 年的&#xff0c;从一名底层的技术员成长为…...

计算机系统基础实训五—CacheLab实验

实验目的与要求 1、让学生更好地应用程序性能的优化方法&#xff1b; 2、让学生更好地理解存储器层次结构在程序运行过程中所起的重要作用&#xff1b; 3、让学生更好地理解高速缓存对程序性能的影响&#xff1b; 实验原理与内容 本实验将帮助您了解缓存对C程序性能的影响…...

PHP框架之CodeIgniter框架

CodeIgniter框架详细说明 CodeIgniter是一个简单而强大的PHP框架&#xff0c;专为快速开发Web应用程序而设计。它遵循MVC&#xff08;模型-视图-控制器&#xff09;设计模式&#xff0c;为开发者提供了丰富的功能和灵活性&#xff0c;同时保持代码的轻量级和易于管理。CodeIgn…...

714. 买卖股票的最佳时机含手续费

714. 买卖股票的最佳时机含手续费 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;ExplanationSummary 参考代码&#xff1a;_714买卖股票的最佳时机含手续费 错误经验吸取 原题链接&#xff1a; 714. 买卖股票的最佳时机含手续费 https://leetcode.cn/probl…...

Linux系统查看程序内存及CPU占用

文章目录 1.free命令2.top命令3.PS命令3.1 查看内存占用前10位&#xff1a;3.2 查看CPU占用前10位 参考文档 1.free命令 可以通过free命令查看物理内存占用情况 #单位KB free #单位MB free -m #单位GB free -h 2.top命令 输入top命令&#xff0c;会输出定时刷新的程序PID、内…...

数据结构7---图

一、定义 对于图的定义&#xff0c;我们需要明确几个注意的地方:一线性表中我们把数据元素叫元素&#xff0c;树中叫结点&#xff0c;在途中数据元素我们则称之为顶点(Vertex)。 对于图的定义&#xff0c;我们需要明确几个注意的地方: 线性表中我们把数据元素叫元素&#xf…...

Excel 如何复制单元格而不换行

1. 打开excle, sheet1右键单击>查看代码>插入>模块 输入代码 Sub CopyText() Updated by NirmalDim xAutoWrapper As ObjectSet xAutoWrapper New DataObject or GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")xAutoWrapper.SetText ActiveC…...

前端 CSS 经典:mix-blend-mode 属性

前言&#xff1a;这是一个混合属性&#xff0c;作用是将两个颜色混合生成一个新颜色。可以将视频和文字相融合&#xff0c;产生动态文字效果。 效果 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8" />&l…...

OpenCV--滤波器(一)

低通滤波器 代码和笔记 代码和笔记 import cv2 import numpy as np""" 滤波器--用于图像处理的重要工具&#xff0c;它们可以根据图像中像素的邻域信息来修改像素值&#xff0c;以实现去噪、模糊、锐化、边缘检测等效果。低通滤波器&#xff08;Low-pass Filte…...

MK的前端精华笔记

文章目录 MK的前端精华笔记第一阶段&#xff1a;前端基础入门1、&#xff08;1&#xff09;、&#xff08;2&#xff09;、 2、3、4、5、6、7、 第二阶段&#xff1a;组件化与移动WebAPP开发1、&#xff08;1&#xff09;、&#xff08;2&#xff09;、 2、3、4、5、6、7、 第三…...

低代码平台框架:开源选型、实践与应用深度解析

文章目录 1.1 低代码平台的重要性与应用背景2.1 表单建模2.2 流程设计2.3 报表&#xff08;打印&#xff09;可视化2.4 代码生成器2.5 系统管理2.6 前端UI开源选型3.1 如何选择合适的开源框架3.2 市场上的主要开源低代码平台对比3.3 开源项目的技术栈与优缺点分析 5.1 成功案例…...

深度学习500问——Chapter12:网络搭建及训练(3)

文章目录 12.3.5 Caffe有哪些接口 12.4 网络搭建有什么原则 12.4.1 新手原则 12.4.2 深度优先原则 12.4.3 卷积核size一般为奇数 12.4.4 卷积核不是越大越好 12.5 有哪些经典的网络模型值得我们去学习的 12.6 网络训练有哪些技巧 12.6.1 合适的数据集 12.6.2 合适的预…...

Android使用DevRing框架搭建数据库实体类以及使用

一、引用DevRing依赖 //导入DevRing依赖implementation com.ljy.ring:devring:1.1.8创建数据库表的依赖implementation org.greenrobot:greendao:3.2.2 // add libraryimplementation org.greenrobot:greendao-generator:3.0.0 二、修改工程目录下的.idea->gradle.xml文件&…...

高效BUG管理:定级、分类和处理流程

高效BUG管理&#xff1a;定级、状态跟踪与处理全流程 前言一、BUG的定义二、BUG的定级三、BUG的状态四、BUG的处理流程1. BUG报告2. BUG确认3. BUG修复4. BUG验证5. BUG关闭 五、常见问题与解决方案六、总结 前言 在测试工作中&#xff0c;BUG的定级和分类是一个重要环节&…...

Vue.js 中属性绑定的详细解析:冒号 `:` 和非冒号的区别

Vue.js 中属性绑定的详细解析&#xff1a;冒号 : 和非冒号的区别 在 Vue.js 中&#xff0c;属性绑定是一个重要的概念&#xff0c;它决定了如何将数据绑定到 DOM 元素的属性上。Vue.js 提供了两种方式来绑定属性&#xff1a;使用冒号 : 进行动态绑定&#xff0c;或直接书写属性…...

微信小程序的开发

前端&#xff1a;微信小程序开发的技术 后端&#xff1a;springboot的框架 一&#xff1a;微信小程序环境的搭建 1. 访问微信开发者官⽅⽹站的⼩程序开发⼯具下载⻚⾯。 2. 根据你的操作系统&#xff08;Windows、macOS或Linux&#xff09;选择合适的版本进⾏下载。 3. 下…...

单片机里面中断状态寄存器是什么

中断状态寄存器是存在于许多微控制器和硬件设备中的一个特殊类型的寄存器&#xff0c;用于指示发生了哪些中断事件。当中断发生时&#xff0c;相应的中断状态寄存器中的一个或多个位会被硬件设置为1。软件可以通过读取这个寄存器来确定哪些中断需要处理&#xff0c;并通过写回特…...

在Java中如何处理并发操作和继承

1、并发操作 1、使用线程安全的数据结构 Java提供了许多线程安全的集合类&#xff0c;如Vector、Hashtable、ConcurrentHashMap、CopyOnWriteArrayList等。这些类内部实现了同步机制&#xff0c;可以在多线程环境中安全地使用。 2、同步块和同步方法 使用synchronized关键字…...

Android常用加解密算法总结

Android开发中对于数据的传输和保存一定会使用加密技术&#xff0c;加密算法是最普遍的安保手段&#xff0c;多数情况数据加密后在需要使用源数据时需要再进行解密&#xff0c;但凡是都有例外。下面从可逆加密、不可逆、不纯粹加密三种方式记录一下常见的加解密算法。 加密技术…...

在线医疗诊断平台开发教程大纲 (Java 后端,Vue 前端)—实践篇-02

第三步:创建实体类和 Mapper 文件 现在我们已经设计好了数据库表结构,接下来要使用 MyBatis 将这些表映射到 Java 对象,以便在代码中进行操作。 1. 创建实体类 在 src/main/java/<your_package>/entity 目录下 (如果没有该目录,请手动创建),创建与数据库表对应的实…...

HAL库使用FreeRTOS实时操作系统时配置时基源(TimeBase Source)

需要另外的定时器&#xff0c;用systic的时候生成项目会有警告 https://blog.51cto.com/u_16213579/10967728...

从动态代理角度简单理解Spring AOP

1. 概述 动态代理 是指在运行时&#xff0c;动态地创建目标类的代理对象&#xff0c;并对其中特定的方法进行拦截或增强的技术。这种技术主要用于在不修改目标类代码的情况下&#xff0c;增强目标类的功能。 在Java中&#xff0c;动态代理主要基于Java的反射机制和接口来实现…...

UE5文件操作

首先在虚幻引擎中创建UMyBlueprintFunctionLibrary类&#xff0c;可以在该类中写我们重复利用的功能&#xff0c;并且这些功能不依赖于特定的游戏对象&#xff0c;方便全局调用。 1.文件的读取和写入 UFUNCTION(BlueprintCallable, Category "File")static bool lo…...

新人开发新系统,旧人维护旧系统

通常来说旧系统存在一些难以解决的问题&#xff0c;软件架构及逻辑实现可能会有一定的缺陷和复杂度&#xff0c;甚至有些烂系统可以称为”焦油坑“&#xff0c;意思是出现问题难以分析解决&#xff0c;谁来谁陷进去。因此&#xff0c;如果同时存在新系统&#xff08;可能正在开…...

算法与数据结构高手养成:朴素的贪心法(上)最优化策略

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…...

栈的特性及代码实现(C语言)

目录 栈的定义 栈的结构选取 链式储存结构和顺序栈储存结构的差异 栈的代码实现 "stack.h" "stack.c" 总结 栈的定义 栈&#xff1a;栈是限定仅在表尾进行插入和删除操作的线性表。 我们把运行插入的和删除的一段叫做栈顶&#xff08;TOP&#xff…...