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

Java 设计模式-代理模式

目录

概述

一. 什么是代理模式

1. 举例说明

二. 代理模式作用

1. 保护代理

2. 增强功能

3. 代理交互

4. 远程代理:

三. 代理模式3个角色

四. 静态代理

1. 代码示例:

五. JDK动态代理

1. 代码示例:

六. CGLIB 动态代理

1.代码示例

 七. JDK动态代理和CGLIB动态代理区别

八. 两种在spring的使用


概述

        代理模式(Proxy Pattern)是设计模式中的一种结构型模式,其核心思想是通过创建一个代理对象来间接访问实际对象(也称为主题对象),从而在不改变实际对象的前提下,为实际对象添加额外的功能或控制。

代理模式根据实现方式可分:

  1. 接口实现:某个类必须有实现的接口,如果某个类没有实现接口,那么这个类就不能通过 JDK 产生动态代理了
    1. 静态代理
    2. 动态代理
  2. 继承实现:是 CGLIB 通过动态生成一个需要被代理类的子类(即被代理类作为父类),该子类重写被代理类的所有不是 final 修饰的方法,(使用 Java 反射技术创建代理类的实例)CGLIB 是一个第三方库

一. 什么是代理模式

        代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。它使得客户不能直接与真正的目标对象通信。代理对象是目标对象的代表,其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉。

        代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的,同时也在一定程度上面减少了系统的耦合度。

1. 举例说明

        以卖房为例:房东 A 要卖房,客户 B 要买房,

没有代理模式情况:

  1. 房东 A 要卖房(可能要贴小广告卖房)
  2. 带买家 B 来看房
  3. 买家 B 非常满意,交易达成(出售成功)

使用代理模式:

  1. 房东 A 要卖房
  2. 找到代理 C ,由 C 去做卖房信息发布
  3. 代理 C 带有购买意向的客户看房
  4. 买家 B 很满意,交易达成

在这个例子中房东只需找到代理即可,其他发布房源信息和看房都由代理去做。

二. 代理模式作用

1. 保护代理

        代理可以为实际对象提供一层保护,确保对象不会被不信任的调用者直接访问。

2. 增强功能

        在程序中,需要给某个对象的功能进行功能增强的时候,可以考虑找一个代理进行增强,例如:Spring 框架中的 AOP 切面编程就是对代理模式的经典应用。

3. 代理交互

        在程序中,A对象无法和B对象直接交互时,也可以使用代理模式来解决。

4. 远程代理

        代理可以作为远程对象的本地代表,隐藏对象位于不同地址空间的事实,使得远程调用就像本地调用一样。

三. 代理模式3个角色

  1. 目标对象:目标对象也就是被代理对象(对应着被代理类)
  2. 代理对象:代理对象对应着代理类
  3. 公共接口:目标对象和代理对象的公共接口(目标对象和代理对象都需要实现这个接口)注意:在JDK中是通过接口实现代理的,但是在cglib中使用的是继承来实现动态代理的

UML图

四. 静态代理

        静态代理实现相对来比较简单,静态代理是代理模式中较简单的一种模式,它在编译时就已经确定代理类和目标类的关系。

1. 代码示例:

  1. 创建公共接口
    package com.demo.proxy;/*** 文件名:Subject* 创建者:* 创建时间:2024-09-05* 描述:公共接口*/
    public interface Subject {void info();
    }
    
  2. 创建目标类
    package com.demo.proxy;/*** 文件名:RealSubject* 创建者:* 创建时间:2024-09-05* 描述: 目标类*/
    public class RealSubject implements Subject{@Overridepublic void info() {System.out.println("被代理对象方法执行。。。");}
    }
    
  3. 创建代理类
    package com.demo.proxy;/*** 文件名:ProxySubject* 创建者:* 创建时间:2024-09-05* 描述: 代理类*/
    public class ProxySubject implements Subject{private Subject subject;public ProxySubject(Subject subject) {this.subject = subject;}@Overridepublic void info() {perReqs();subject.info();postReqs();}private void perReqs(){System.out.println("记录请求日志");}private void postReqs(){System.out.println("记录响应日志");}}
    
  4. 测试类
    package com.demo.proxy;/*** 文件名:Main* 创建者:* 创建时间:2024-09-05* 描述: 测试类*/
    public class Main {public static void main(String[] args) {//1.创建目标对象Subject subject = new RealSubject();//2.创建代理对象(将目标对象传入代理对象构造中)Subject sub = new ProxySubject(subject);sub.info();}
    }
    
  5. 测试结果

五. JDK动态代理

        java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。

        代理类在程序运行时利用反射机制动态创建而成,主要分为jdk动态代理cglib动态代理

        JDK 动态代理类的字节码在程序运行时由 Java 反射机制动态生成,无需手工编写它的源代码。
        动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为 Java 反射机制可以生成任意类型的动态代理类。

1. 代码示例:

参数说明:

Proxy类的静态方法 newProxyInstance() 参数:

  • loader:类加载器,使用本类的类加载器即可,或者 target 对象的类加载器也行。
  • interfaces:接口数组,表示被代理类实现的接口,因可能会实现多个接口,所以这里是数组的形式。
  • InvocationHandler:核心,在这里创建一个内部实现类实现InvocationHandler接口,重写invoke方法
    invoke 里的参数 proxy 是代理类的实例,method是代理类的实例执行的方法,args则是执行的方法里面的参数,
    我们可以在这里对执行核心业务逻辑前后增加代码。method.invoke(target, args)这里是用了反射的原理让target对象去执行method方法。
  1. 定义接口
    package com.demo.proxy.dynamic;/*** 文件名:UserService* 创建者:* 创建时间:2024-09-05* 描述:业务服务接口*/
    public interface IUserService {boolean login(String name,String pwd);void signOut(String name);
    }
    
  2. 定义接口实现类(也就是业务实现类)
    package com.demo.proxy.dynamic;/*** 文件名:UserService* 创建者:* 创建时间:2024-09-05* 描述:业务实现类*/
    public class UserService implements IUserService{/*** 登录* @param name* @param pwd* @return*/@Overridepublic boolean login(String name,String pwd) {System.out.println(name+":登录成功");return true;}/*** 退出* @param name*/@Overridepublic void signOut(String name) {System.out.println(name +": 退出成功");}
    }
    
  3. 定义代理类(无需实现接口)
    package com.demo.proxy.dynamic;import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;/*** 文件名:DefineProxy* 创建者:* 创建时间:2024-09-05* 描述:动态代理类*/
    public class DefineProxy {private Object target;public DefineProxy(Object target){this.target = target;}public Object createProxy(){return Proxy.newProxyInstance(DefineProxy.class.getClassLoader(), this.target.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {perName(method.getName());Object invoke = method.invoke(target, args);postName(method.getName());return invoke;}});}/*** 前置方法* @param name*/private void perName(String name){System.out.println(name+"方法-前置执行");}/*** 后置方法* @param name*/private void postName(String name){System.out.println(name+"方法-后置执行");}
    }
    
  4. 定义测试类
    package com.demo.proxy.dynamic;/*** 文件名:Main* 创建者:* 创建时间:2024-09-05* 描述:测试类*/
    public class Main {public static void main(String[] args) {//1.创建目标对象UserService userService = new UserService();//2.创建代理对象DefineProxy defineProxy = new DefineProxy(userService);//3.调用生成代理方法IUserService proxy = (IUserService) defineProxy.createProxy();//4.代理执行方法boolean flg = proxy.login("小明","12345");System.out.println("返回值:"+flg);System.out.println("=============================");proxy.signOut("小明");}
    }
    
  5. 测试结果截图
  6. 修改动态代理类(通过实现 InvocationHandler 接口来实现代理 )
    package com.demo.proxy.dynamic;import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;/*** 文件名:DefineProxyTwo* 创建者:宁贝贝* 创建时间:2024-09-05* 描述:动态代理类,通过实现接口*/
    public class DefineProxyTwo implements InvocationHandler {private Object target;public DefineProxyTwo(Object target){this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {perName(method.getName());Object res = method.invoke(target,args);postName(method.getName());return res;}/*** 前置方法* @param name*/private void perName(String name){System.out.println(name+"方法-前置执行");}/*** 后置方法* @param name*/private void postName(String name){System.out.println(name+"方法-后置执行");}
    }
    
  7. 修改测试类
    package com.demo.proxy.dynamic;import java.lang.reflect.Proxy;/*** 文件名:MainTwo* 创建者:* 创建时间:2024-09-05* 描述:测试类*/
    public class MainTwo {public static void main(String[] args) {//1.创建被代理对象UserService userService = new UserService();//2.获取被代理对象的类加载器,用作生成代理对象的必要参数ClassLoader classLoader = userService.getClass().getClassLoader();//3.获取被代理对象的实现接口,// 用作生成代理对象的必要参数// 方法映射就是基于这个参数实现的Class<?>[] interfaces = userService.getClass().getInterfaces();//4.获取被代理对象的增强主题类,用作生成代理对象的必要参数DefineProxyTwo defineProxyTwo = new DefineProxyTwo(userService);//5.生成代理对象的核心代码IUserService proxyInstance = (IUserService) Proxy.newProxyInstance(classLoader, interfaces, defineProxyTwo);// 使用代理对象执行方法proxyInstance.login("星星","765432");System.out.println("==========================");proxyInstance.signOut("星星");}
    }
    

六. CGLIB 动态代理

        JDK 中提供的生成动态代理类的机制有个鲜明的特点是:某个类必须有实现的接口,如果某个类没有实现接口,那么这个类就不能通过 JDK 产生动态代理了。

        CGLIB(Code Generation Library)是一个强大的、高性能、高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。
        CGLIB 通过动态生成一个需要被代理类的子类(即被代理类作为父类),该子类重写被代理类的所有不是 final 修饰的方法,并在子类中采用方法拦截的技术拦截父类所有的方法调用,进而织入横切逻辑。此外,因为 CGLIB 采用整型变量建立了方法索引,这比使用 JDK 动态代理更快(使用 Java 反射技术创建代理类的实例)。

CGLib 创建某个类 A 的动态代理类的模式是:

  1. 查找 A 上的所有非 final 的 public 类型的方法定义;
  2. 将这些方法的定义转换成字节码;
  3. 将组成的字节码转换成相应的代理的 class 对象;
  4. 实现 MethodInterceptor 接口,用来处理 对代理类上所有方法的请求(这个接口和JDK动态代理InvocationHandler的功能和角色是一样的)

1.代码示例

  1. 定义普通业务类
    package com.demo.proxy.cglib;/*** 文件名:UserService* 创建者:* 创建时间:2024-09-05* 描述:一个普通的业务类*/
    public class UserService{/*** 登录* @param name* @param pwd* @return*/public boolean login(String name,String pwd) {System.out.println(name+":登录成功");return true;}/*** 退出* @param name*/public void signOut(String name) {System.out.println(name +": 退出成功");}
    }
    
  2. 定义CGLIB动态代理类
    package com.demo.proxy.cglib;import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 文件名:CGLibProxy* 创建者:* 创建时间:2024-09-05* 描述:cglib动态代理类*/
    public class CGLibProxy implements MethodInterceptor {private Object target;public CGLibProxy(Object target) {this.target = target;}public Object createProxy(){//cglib中的增强器,用来创建动态代理Enhancer enhancer = new Enhancer();//设置要创建动态代理的类enhancer.setSuperclass(target.getClass());//设置回调,这里相当于是对于代理类上所有方法的调用,都会调用callback,而callback则需要实现intercept()方法进行拦截。enhancer.setCallback(this);//创建代理类return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("cglib 代理开始...");Object object = proxy.invokeSuper(obj,args);System.out.println("cglib 代理结束...");return object;}
    }
    
  3. 定义测试类
    package com.demo.proxy.cglib;/*** 文件名:Main* 创建者:* 创建时间:2024-09-05* 描述:测试类*/
    public class Main {public static void main(String[] args) {//1.创建被代理对象UserService userService = new UserService();//2.创建CGLibProxy对象CGLibProxy cgLibProxy = new CGLibProxy(userService);//3.调用createProxy创建代理对象UserService proxy = (UserService)cgLibProxy.createProxy();//4.代理执行方法boolean res = proxy.login("晓月","5676543");System.out.println("登录结果:"+res);System.out.println("--------------------------------");proxy.signOut("晓月");System.out.println("=================================");//其实上面那几个步骤可以一行代码全搞定UserService us = (UserService)new CGLibProxy(new UserService()).createProxy();boolean result = us.login("小红","13123123");System.out.println("登录结果:"+result);System.out.println("--------------------------------");us.signOut("小红");}
    }
    
  4. 测试结果

 七. JDK动态代理和CGLIB动态代理区别

  1. 实现原理:JDK动态代理是基于Java反射机制实现的,它要求目标类必须实现一个或多个接口,代理对象在运行时动态创建,通过实现目标类接口的方式来代理目标类。 CGLIB代理则是基于ASM字节码框架实现的,它可以代理没有实现接口的目标类。CGLIB在运行时通过动态生成目标类的子类来实现代理。
  2. 性能表现:JDK动态代理因为需要实现目标类接口,所以它的性能相对较低,但是它的应用场景更为广泛,适用于大多数情况下的代理需求。 CGLIB代理则因为不需要实现目标类接口,所以它的性能相对较高,但是它不能代理final类和final方法,以及一些无法生成子类的类。
  3. 应用场景:JDK动态代理适用于代理接口的场景,例如Spring中的事务处理、日志记录等。 CGLIB代理适用于代理类的场景,例如Spring中的AOP切面编程等。

八. 两种在spring的使用

        如果被代理对象实现了需要被代理的接口,则使用 JDK 的动态代理,否则便使用 CGLIB 代理,在spring中它会自动根据使用情况进行切换,但是如果你缺少CGLIB依赖肯定是会报错。需要添加 cglib 依赖包。

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

相关文章:

Java 设计模式-代理模式

目录 概述 一. 什么是代理模式 1. 举例说明 二. 代理模式作用 1. 保护代理 2. 增强功能 3. 代理交互 4. 远程代理&#xff1a; 三. 代理模式3个角色 四. 静态代理 1. 代码示例&#xff1a; 五. JDK动态代理 1. 代码示例&#xff1a; 六. CGLIB 动态代理 1.代码示…...

CTF靶场之BUUCTF介绍

最后开始关注CTF&#xff0c;我们先了解一下什么CTF:CTF&#xff08;Capture The Flag&#xff09;中文一般译作夺旗赛&#xff0c;在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式,最后以夺取FLAG为成功。 从网上找了一个免费的靶场——BUUCTF&#xf…...

学会分析问题,画出分析图,解释问题过程,找出规律 ;整数数组分为左右2个部分,左边位奇数右边偶数

// 整数数组左边是奇数右边是偶数.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include<stdio.h> void swap(int& a,int& b) {int tempa;ab;btemp; } int main(int argc, char* argv[]) {int a[7]{1,2,3,4,5,…...

数学基础 -- 线性代数正交多项式之勒让德多项式展开推导

勒让德多项式展开的详细过程 勒让德多项式是一类在区间 [ − 1 , 1 ] [-1, 1] [−1,1] 上正交的多项式&#xff0c;可以用来逼近函数。我们可以将一个函数表示为勒让德多项式的线性组合。以下是如何推导勒让德多项式展开系数 a n a_n an​ 的详细过程。 1. 勒让德展开的基本…...

Redis实战宝典:从主从模式、哨兵模式、集群模式一步步理解Redis集群

目录标题 Redis 集群的三种模式主从复制主从复制概念主从复制原理主从复制优缺点 哨兵集群哨兵概念哨兵功能下线判断主库选举故障转移哨兵模式优缺点 Cluser 集群Redis 集群的数据分片 Redis 集群的三种模式 在生产环境中&#xff0c;我们使用 Redis 通常采用集群模式&#xf…...

828华为云征文|华为云Flexus X搭建借贷管理系统、二次开发借贷小程序 前端源码uniapp

在华为云828 B2B企业节的盛宴中&#xff0c;Flexus X实例以其卓越的算力性能和灵活的资源配置脱颖而出。对于追求极致性能、渴望在借贷管理、电商交易等场景中脱颖而出的您来说&#xff0c;Flexus X无疑是最佳拍档。搭载创新加速引擎&#xff0c;让您的自建MySQL、Redis、Nginx…...

网站安全需求分析与安全保护工程

网站安全威胁与需求分析 网站安全概念 网站&#xff1a;是基于B/S技术架构的综合信息服务平台&#xff0c;主要提供网页信息及业务后台对外接口服务。 网站安全性&#xff1a; 机密性&#xff1a;网站信息及相关数据不被授权查看或泄露完整性&#xff1a;网站信息及数据不能…...

后谷歌时代

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

【CMake编译报错小复盘】CMAKE_CUDA_ARCHITECTURES,CMake version,GCC version问题

今天在写大模型量化推理框架时遇到了一些编译上的错误&#xff0c;简单复盘一下问题和解决方案&#xff1a; 问题1&#xff1a;CMAKE_CUDA_ARCHITECTURES 报错信息&#xff1a; CMake Error: CMAKE_CUDA_ARCHITECTURES must be non-empty if set cmake和cuda相关的报错通常都…...

PMP--一、二、三模--分类--14.敏捷--技巧--DoDDoR

文章目录 技巧DoD&DoR 二模14.敏捷--术语表--完成的定义DoD--Definition of Done--是指一个项目什么时候可以被认为是“完成”的标准&#xff0c;它可以包括各种质量和功能的具体要求。--它是团队需要满足的所有标准的核对单&#xff0c;只有可交付成果满足该核对单才能视为…...

【大数据】如何读取多个Excel文件并计算列数据的最大求和值

导语&#xff1a; 在数据分析和处理中&#xff0c;我们经常需要从多个Excel文件中提取数据并进行计算。本文将带您通过一个实用的Python教程&#xff0c;学习如何读取D盘目录下特定文件夹内的多个Excel文件&#xff0c;并计算特定列数据的最大求和值。 文章目录 一、准备工作二…...

【运维项目经历|043】上云项目-服务从物理机迁移到AWS云服务器

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 ​ 🏅阿里云开发者社区专家博主 💊交流社区:CSDN云计算交流社区欢迎您的加入! 文章目录 项目名称项目背景项目目标项目成…...

【OpenCV】灰度化和二值化处理图像

文章目录 1. 图像灰度化处理对比2. 代码示例3. 二值化处理 1. 图像灰度化处理对比 2. 代码示例 #include <opencv2/opencv.hpp> using namespace cv;int main() {Mat currentImage imread("path_to_image.jpg"); // 读取彩色图像Mat grayImage;// 将彩色图像…...

【生命不息,动出奇迹!】多系统萎缩患者必看

亲爱的朋友们&#xff0c;当我们面对生活的挑战&#xff0c;尤其是像多系统萎缩&#xff08;MSA&#xff09;这样的复杂疾病时&#xff0c;保持乐观与积极&#xff0c;寻找适合自己的锻炼方式显得尤为重要&#xff01;&#x1f4aa; MSA虽然会影响身体的多个系统&#xff0c;包…...

Verilog FPGA 仿真 控制任务

在Verilog仿真中&#xff0c;我们可以使用一些控制语句和系统任务来管理仿真过程。这些语句和任务可以帮助我们控制仿真的进行并输出必要的信息。 1. $stop&#xff1a;这是一个系统任务&#xff0c;用于停止运行仿真。在ModelSim中&#xff0c;可以继续仿真。 2. $stop(n)&…...

在Vision Pro上实现五子棋、益智休闲游戏:一个可二次开发的框架

苹果Vision Pro平台的推出,空间计算技术迎来了新的发展机遇。在这一背景下,物流游戏(Logistics Game)作为一个为Vision Pro平台量身打造的空间计算战略游戏,不仅展示了空间计算的魅力,也为开发者提供了一个可参考的框架。本文将介绍物流游戏的核心玩法,并总结其开发过程…...

使用 `Vitesse Uni App` 创建微信小程序并配置 uview-plus 和 alovajs

使用 Vitesse Uni App 创建微信小程序 Vitesse Uni App&#xff1a;https://vitesse-docs.netlify.app/ UI&#xff1a;https://uview-plus.jiangruyi.com/components/intro.html 编辑器&#xff1a;VScode 安装 Volar&#xff08;Vue Offices&#xff09;插件 创建项目 pnpm …...

C#迭代器和接口IEnumerable,IEnumerator

一.迭代器 学过C的都知道&#xff0c;迭代器是STL中的一个类&#xff0c;用来遍历容器。 vector<int>::iterator iter; for (iter v1.begin(); iter ! v1.end(); iter) C#中迭代器也是用来遍历集合&#xff0c;本质上是一个类/接口(IEnumerator)&#xff0c;可以解决…...

通信工程学习:什么是IP-CAN(IP连接接入网)

IP-CAN&#xff1a;IP连接接入网 IP-CAN&#xff08;IP连接接入网&#xff09;是一个通过IP实现用户设备&#xff08;UE&#xff09;与IP多媒体子系统&#xff08;IMS&#xff09;实体之间连通的网络实体和接口的集合。以下是对IP-CAN的详细解释&#xff1a; 一、定义与概述 1…...

使用 MongoDB 构建 AI:Patronus 如何自动进行大语言模型评估来增强对生成式 AI 的信心

大语言模型可能不可靠&#xff0c;这几乎算不上头条新闻。对于某些用例&#xff0c;这可能会带来不便。而对于其他行业&#xff0c;尤其是受监管行业&#xff0c;后果则要严重得多。于是&#xff0c;业内首个大语言模型自动评估平台 Patronus AI 应运而生。 Patronus AI 由 Met…...

openpose1.7.0编译 cuda12.2 cudnn 8.9.7.29 python3.7

参考链接&#xff1a; openpose(windows11)安装及常见问题及解决方案_openpose windows-CSDN博客 openpose笔记--Win11编译安装OpenPose(Python API)_openpose安装-CSDN博客 https://zhuanlan.zhihu.com/p/383661308 遇到问题&#xff1a; 1、cmake时&#xff0c;手动设置…...

【华为OD流程】性格测试选项+注意事项

可上 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1441了解算法冲刺训练(备注【CSDN】否则不通过) 文章目录 相关推荐阅读性格测试形式性格测试题型性格测试原则性格测试一致性性格测试选项举例最合适的性格适中的性格不适合的性格答题方法分享特别注意华为OD算法/大厂…...

《生物学教学》

《生物学教学》杂志是由国家教育部主管、华东师范大学主办&#xff0c;向国内外正式发行的全国教育类核心期刊。主要栏目有&#xff1a;生物科学综述、课程标准与教材、当代教育论坛、国外教育动态、教师教育、教育教学研究、教学设计案例、信息技术、考试与评价、实验教学、探…...

C++ 标准库的典型内容

目录 C 标准库的典型内容1. std::declval定义使用方法常见用途注意事项 2. std::true_type 和 std::false_type定义使用方法常见用途注意事项 3. std::void_t定义使用方法常见用途注意事项 4. std::conditional定义使用方法常见用途注意事项 5. std::function定义使用方法常见用…...

【C++初阶】:C++入门,引用概念及其性质

文章目录 一、引用的概念二、引用的语法规则1、引用特性2、常引用 二、引用的使用场景1. 引用做参数2. 引用做返回值 三、引用和指针的区别 一、引用的概念 首先明确一下&#xff0c;引用不是定义一个新的变量&#xff0c;而是给已经存在的变量起一个别名&#xff0c;变量和他…...

Linux 中的 crontab 命令介绍以及使用

文章目录 Linux Crontab 完全指南什么是 Crontab&#xff1f;Crontab 文件的基本格式特殊符号解释&#xff1a; 如何使用 Crontab查看当前用户的 Crontab编辑 Crontab删除 Crontab Crontab 示例每天晚上 12 点备份数据库每个工作日的早上 9 点发送日报每隔 15 分钟清理临时文件…...

单片机组成原理

大纲 C语言指针如何与硬件对应 底层疑问的源头 我已造好轮子&#xff0c;等你来理解 外设电路大概是什么结构 解决底层开发中关于配置、寄存器) 外设电路的疑问 从此可以快速上手新的单片机、新的外设芯片 对外设芯片的内部结构有本质理解&#xff0c;看手册不再是问题 固件库…...

《机器学习》—— SVD奇异值分解方法对图像进行压缩

文章目录 一、SVD奇异值分解简单介绍二、代码实现—SVD奇异值分解方法对图像进行压缩 一、SVD奇异值分解简单介绍 SVD&#xff08;奇异值分解&#xff09;是一种在信号处理、统计学、线性代数、机器学习等多个领域广泛应用的矩阵分解方法。它将任何 mn 矩阵 A 分解为三个特定矩…...

英文文本预处理——文本清理

文本清理定义 文本清理是英文文本预处理的重要步骤,旨在提高数据质量和一致性。以下是文本清理的具体内容: 去除标点符号 (Removing Punctuation): 删除文本中的标点符号,如句号、逗号、问号等。这一步骤有助于减少文本噪音,使得文本分析更加专注于有意义的词汇内容。 去…...

Spring Boot 注解探秘:常用配置值读取注解的魔力

在 Spring Boot 应用开发中&#xff0c;我们会常常借助Apollo&#xff0c;Spring Cloud Config等配置中心来集中管理配置信息&#xff0c;在拥有配置信息之后&#xff0c;高效且准确地读取这些配置信息无疑是极为关键的一环。今天我们就来介绍几个常用的用于配置值读取的注解。…...