Springcache+xxljob实现定时刷新缓存
目录
SpringCache详解
SpringCache概述
核心原理
接口抽象与多态
AOP动态代理
核心注解以及使用
公共属性
cacheNames
KeyGenerator:key生成器
key
condition:缓存的条件,对入参进行判断
注解
xxl-job详解
Springcache+Redis实现缓存
xxl-job定时刷新缓存
SpringCache详解
SpringCache概述
早期的Java开发中,缓存技术需要借助第三方库(Ehcache、Guava等),导致了代码与具体缓存实现强耦合。此时缺乏统一缓存规范,并且在企业中更换缓存组件成本较高。
Spring框架在3.1版本首次引入缓存抽象层,定义了Cache和CacheManager接口,通过注解(如@Cacheable)实现声明式缓存。随后在Spring4.1开始全面支持JCache规范(2012年提出的JSR-107规范草案),通过JCacheManager集成第三方缓存实现,自此开发者可以通过标准接口切换缓存方案,实现了通过标准接口隔离业务代码与具体缓存的抽象解耦,符合“开方-封闭原则”。
Spring Cache 是 Spring 框架提供的抽象化缓存解决方案,通过注解和 AOP 技术简化了缓存逻辑的集成。它并不直接管理缓存存储,而是作为统一接口,支持多种缓存实现(如 Ehcache、Redis、Caffeine 等),使开发者能够通过声明式注解快速为方法添加缓存功能,从而减少重复计算,提升系统性能。
核心原理
接口抽象与多态
SpringCache定义了两大核心接口实现缓存标准化:
- Cache接口
定义缓存基本操作(get、put、evict),不同缓存技术(如Redis、Ehcache)通过实现该接口完成适配,例如:
RedisCache通过RedisTemplate操作Redis数据
ConcurrentMapCache使用本地内存Map存储数据
- CacheManager接口
管理多个Cache实例的生命周期,支持多级缓存混合使用。
(EhCacheCacheManager解析ehcahe.xml配置,RedisCacheManager配置TTL和序列化策略)
AOP动态代理
SpringCache通过CacheInterceptor拦截器实现方法级缓存空值:

说明:
- 将
invocation.proceed()封装为CacheOperationInvoker实例,延迟执行原始方法。 - 捕获所有
Throwable并封装为ThrowableWrapper,避免缓存逻辑干扰异常类型。 - 调用
execute:传递方法调用器、目标对象、方法对象和参数,进入缓存处理核心逻辑。
然后一直跟进execute方法,最终找到处理缓存的主逻辑:
@Nullable
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {if (contexts.isSynchronized()) {CacheOperationContext context = (CacheOperationContext)contexts.get(CacheableOperation.class).iterator().next();if (!this.isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {return this.invokeOperation(invoker);}Object key = this.generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);Cache cache = (Cache)context.getCaches().iterator().next();try {return this.wrapCacheValue(method, this.handleSynchronizedGet(invoker, key, cache));} catch (Cache.ValueRetrievalException var10) {Cache.ValueRetrievalException ex = var10;ReflectionUtils.rethrowRuntimeException(ex.getCause());}}this.processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT);Cache.ValueWrapper cacheHit = this.findCachedItem(contexts.get(CacheableOperation.class));List<CachePutRequest> cachePutRequests = new ArrayList();if (cacheHit == null) {this.collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);}Object cacheValue;Object returnValue;if (cacheHit != null && !this.hasCachePut(contexts)) {cacheValue = cacheHit.get();returnValue = this.wrapCacheValue(method, cacheValue);} else {returnValue = this.invokeOperation(invoker);cacheValue = this.unwrapReturnValue(returnValue);}this.collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);Iterator var8 = cachePutRequests.iterator();while(var8.hasNext()) {CachePutRequest cachePutRequest = (CachePutRequest)var8.next();cachePutRequest.apply(cacheValue);}this.processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);return returnValue;
}
流程图:

核心注解以及使用
这里可以看这篇博客:SpringCache详解_spring cache-CSDN博客
公共属性
cacheNames
每个注解中都有自己的缓存名字。该名字的缓存与方法相关联,每次调用时,都会检查缓存以查看是否有对应cacheNames名字的数据,避免重复调用方法。名字可以可以有多个,在这种情况下,在执行方法之前,如果至少命中一个缓存,则返回相关联的值。( Springcache提供两个参数来指定缓存名:value、cacheNames,二者选其一即可,每一个需要缓存的数据都需要指定要放到哪个名字的缓存,缓存的分区,按照业务类型分 )

KeyGenerator:key生成器
缓存的本质是key-value存储模式,每一次方法的调用都需要生成相应的Key, 才能操作缓存。
通常情况下,@Cacheable有一个属性key可以直接定义缓存key,开发者可以使用SpEL语言定义key值。若没有指定属性key,缓存抽象提供了 KeyGenerator来生成key ,具体源码如下,

import java.lang.reflect.Method;public class SimpleKeyGenerator implements KeyGenerator {public SimpleKeyGenerator() {}public Object generate(Object target, Method method, Object... params) {return generateKey(params);}public static Object generateKey(Object... params) {if (params.length == 0) {return SimpleKey.EMPTY;} else {if (params.length == 1) {Object param = params[0];if (param != null && !param.getClass().isArray()) {return param;}}return new SimpleKey(params);}}
}
- 如果没有参数,则直接返回SimpleKey.EMPTY;
- 如果只有一个参数,则直接返回该参数;
- 若有多个参数,则返回包含多个参数的SimpleKey对象。
当然Spring Cache也考虑到需要自定义Key,我们可以通过实现KeyGenerator 接口来重新定义key生成方式
默认的 key 生成器要求参数具有有效的 hashCode() 和 equals() 方法实现。
key
key,缓存的key,如果是redis,则相当于redis的key
可以为空,如果需要可以使用spel表达式进行表写。如果为空,则缺省默认使用key表达式生成器进行生成。默认的 key 生成器要求参数具有有效的 hashCode() 和 equals() 方法实现。key的生成器。key/keyGenerator二选一使用
condition:缓存的条件,对入参进行判断
可以为空,如果需要指定,需要使用SPEL表达式,返回true/false,只有返回true的时候才会对数据源进行缓存/清除缓存。在方法调用之前或之后都能进行判断。
condition=false时,不读取缓存,直接执行方法体,并返回结果,同时返回结果也不放入缓存。
condition=true时,读取缓存,有缓存则直接返回。无则执行方法体,同时返回结果放入缓存(如果配置了result,且要求不为空,则不会缓存结果)。
注意:
condition 属性使用的SpEL语言只有#root和获取参数类的SpEL表达式,不能使用返回结果的#result 。 所以 condition = "#result != null" 会导致所有对象都不进入缓存,每次操作都要经过数据库。
使用实例:
@Override
@Caching(evict = {@CacheEvict(value = RedisConstants.CacheName.ZL_CACHE, key = "'ACTIVE_REGIONS'"),@CacheEvict(value = RedisConstants.CacheName.SERVE_ICON, key = "#id"),@CacheEvict(value = RedisConstants.CacheName.SERVE_TYPE, key = "#id"),@CacheEvict(value = RedisConstants.CacheName.HOT_SERVE, key = "#id")
})
注解
@Cacheable:在方法执行前查看是否有缓存对应的数据,如果有直接返回数据,如果没有调用方法获取数据返回,并缓存起来,也就是查询数据时缓存,将方法的返回值进行缓存
1、unless:条件符合则不缓存,对出参进行判断
unless属性可以使用#result表达式。效果: 缓存如果有符合要求的缓存数据则直接返回,没有则去数据库查数据,查到了就返回并且存在缓存一份,没查到就不存缓存。
condition 不指定相当于 true,unless 不指定相当于 false
当 condition = false,一定不会缓存;
当 condition = true,且 unless = true,不缓存;
当 condition = true,且 unless = false,缓存;
2、sync:是否使用异步,默认是false.
在一个多线程的环境中,某些操作可能被相同的参数并发地调用,同一个 value 值可能被多次计算(或多次访问 db),这样就达不到缓存的目的。针对这些可能高并发的操作,我们可以使用 sync 参数来告诉底层的缓存提供者将缓存的入口锁住,这样就只能有一个线程计算操作的结果值,而其它线程需要等待。当值为true,相当于同步可以有效的避免缓存击穿的问题。
@CachePut:方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中,简单来说就是更新缓存,将方法的返回值放到缓存中
@CacheEvict:用于清空缓存,方法在调用时会从缓存中移除已存储的数据
1、allEntries:是否清空左右缓存。默认为false
当指定了allEntries为true时,Spring Cache将忽略指定的key
2、beforeInvocation:是否在方法执行前就清空,默认为 false(可以看上面的流程图
清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
@Caching:组合多个缓存注解
xxl-job详解
在分布式环境下进行任务调度需要使用分布式任务调度平台,XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
官网:https://www.xuxueli.com/xxl-job/
文档:https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E5%B9%B3%E5%8F%B0XXL-JOB%E3%80%8B
XXL-JOB主要有调度中心、执行器、任务:

调度中心:
负责管理调度信息,按照调度配置发出调度亲你跪求,自身不承担业务代码;
主要职责为执行器管理、任务管理、监控运维、日志管理等;
任务执行器:
负责接收调度请求并执行任务逻辑;
主要职责是执行任务、执行结果上报、日志服务等;
使用xxl-job解决多个jvm进程冲入执行任务问题:

XXL-JOB调度中心可以配置路由策略:第一个、轮询策略、分片等
第一个:每次执行任务都由第一个执行器去执行
轮询:执行器轮番执行
分片:每次执行任务广播给每个执行器让他们同时执行任务
如果根据需求每次执行任务仅由一个执行器去执行任务可以设置路由策略:第一个、轮询
如果根据需求每次执行任务由多个执行器同时执行可以设置路由策略:分片
Springcache+Redis实现缓存
这里借用我最近做的一个项目的代码举例:(功能是将访问频率较高的查询开通区域列表接口进行缓存,并且在每天的凌晨1点实现缓存刷新,更新信息
启用区域后删除已开通区域列表缓存,当之后去查询开通区域列表时重新缓存最新的开通区域列表。
/*** 已开通服务区域列表** @return 区域简略列表*/@Override@Cacheable(value = RedisConstants.CacheName.ZL_CACHE, key = "'ACTIVE_REGIONS'", cacheManager = RedisConstants.CacheManager.FOREVER)public List<RegionSimpleResDTO> queryActiveRegionListCache() {return queryActiveRegionList();}
xxl-job定时刷新缓存
foundations包下面的处理器handler类:定义了xxl-job实现缓存同步任务的定时任务
删除缓存->查询开通区域列表进行缓存->遍历区域列表下的服务类型进行缓存
package com.zhilian.foundations.handler;import com.zhilian.api.foundations.dto.response.RegionSimpleResDTO;
import com.zhilian.foundations.constants.RedisConstants;
import com.zhilian.foundations.service.HomeService;
import com.zhilian.foundations.service.IRegionService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.List;/*** springCache缓存同步任务***/
@Slf4j
@Component
public class SpringCacheSyncHandler {@Resourceprivate IRegionService regionService;@Resourceprivate RedisTemplate redisTemplate;@Resourceprivate HomeService homeService;/*** 已启用区域缓存更新* 每日凌晨1点执行*/@XxlJob(value = "activeRegionCacheSync")public void activeRegionCacheSync() {log.info(">>>>>>>>开始进行缓存同步,更新已启用区域");//删除缓存Boolean delete = redisTemplate.delete(RedisConstants.CacheName.ZL_CACHE + "::ACTIVE_REGIONS");//通过查询开通区域列表进行缓存List<RegionSimpleResDTO> regionSimpleResDTOS = regionService.queryActiveRegionList();//遍历区域对该区域下的服务类型进行缓存regionSimpleResDTOS.forEach(item -> {//区域idLong regionId = item.getId();//删除该区域下的首页服务列表String serve_list_key = RedisConstants.CacheName.SERVE_ICON + "::" + regionId;redisTemplate.delete(serve_list_key);homeService.queryServeIconCategoryByRegionIdCache(regionId);// 删除该区域下的服务类型列表缓存String serve_type_key = RedisConstants.CacheName.SERVE_TYPE + "::" + regionId;redisTemplate.delete(serve_type_key);homeService.queryServeTypeList(regionId);// 删除该区域下的服务类型列表缓存String serve_hot_list_key = RedisConstants.CacheName.HOT_SERVE + "::" + regionId;redisTemplate.delete(serve_hot_list_key);homeService.queryHotServeListByRegionIdCache(regionId);});}
}
代码写好了,需要去xxl-job调度中心对该定时任务进行管理:

填写任务信息:

说明:
调度类型:CRON
固定速度指按固定的间隔定时调度
Cron,通过Cron表达式实现更丰富的定时调度策略
Cron表达式是一个字符串,通过它可以定义调度策略,格式:
{秒数}{分钟}{小时}{日期}{月份}{星期}{年份(可为空)}
xxl-job提供图形界面配置:

运行模式:BEAN和GLUE,bean模式较常用就是在项目工程中编写执行器的任务代码,GLUE是将任务代码编写在调度中心(Bean模式通常有两种形式的实现:类形式和方法形式,此处使用的是方法形式,即在方法上加上@XxlJob注解
JobHandler即任务方法名,填写任务方法上边@XxlJob注解中的名称
任务配置完成,下边启动任务

启动成功:

我们在任务方法上打断点跟踪,任务方法被执行,如下图:

关于springcache的具体使用,可以看看这个文档:SpringCache详解_spring cache-CSDN博客
关于xxl-job的原理、架构分析以及使用,见这篇文档:
3千字带你搞懂XXL-JOB任务调度平台-阿里云开发者社区
相关文章:
Springcache+xxljob实现定时刷新缓存
目录 SpringCache详解 SpringCache概述 核心原理 接口抽象与多态 AOP动态代理 核心注解以及使用 公共属性 cacheNames KeyGenerator:key生成器 key condition:缓存的条件,对入参进行判断 注解 xxl-job详解 SpringcacheRedis实现…...
线性规划建模工具 PuLP 学习指南
PuLP 是一个用 Python 编写的线性规划建模工具,它提供了直观的 API 来定义和求解各种优化问题。以下是学习 PuLP 的全面指南: 1. 安装 PuLP pip install pulp2. 基本概念 问题类型 LpProblem: 表示优化问题LpVariable: 表示决策变量LpConstraint: 表…...
vue2拖拉拽做个模拟公式工具
1. 成图 2. 介绍 就是简单拖拉拽来做个规则运算器,具体运算规则、校验规则自己加。 3. 代码 HTML代码 <template><div class"red-cont"><div class"red-top"><divclass"red-top-left"><div class&quo…...
两点与圆(异或神通)
给出 n 个圆,保证任意两个圆都不相交且不相切。 然后给出两个点 (x1,y1),(x2,y2),保证均不在某个圆上。现在要从 (x1,y1)→(x2,y2) 画条曲线,问这条曲线最少穿过多少次圆的边界? 输入格式 第一行为一个整数 n&…...
Windows查重工具,强烈推荐大家收藏!
我大家在用电脑的时候,是不是发现用得越久,电脑里的软件和文件就越多? 今天我给大家带来的这两款重复文件查找神器,简直就是电脑里的“清洁小能手”,能帮你把那些重复的文件和文件夹找出来。 Easy DupLicate Finder 重…...
使用Python快速接入DeepSeek API的步骤指南
使用Python快速接入DeepSeek API的步骤指南 1. 前期准备 注册DeepSeek账号 访问DeepSeek官网注册账号 完成邮箱验证等认证流程 获取API密钥 登录后进入控制台 → API管理 创建新的API Key并妥善保存 安装必要库 pip install requests # 可选:处理复杂场景 pip…...
使用python完成手写数字识别
入门图像识别的第一个案例,看到好多小伙伴分享,也把自己当初的思路捋捋,写成一篇博客,作为记录和分享,也欢迎各位交流讨论。 实现思路 数据集:MNIST(包含60,000个训练样本和10,000个测试样本) 深度学习框架:Keras(基于TensorFlow) 模型架构:卷积神经网络(CNN) 实…...
OpenLayers:如何控制Overlay的层级?
我最近在使用Overlay的时候遇到了一个问题,我向地图中添加了两种不同的Overlay(下图中的蓝色标牌和粉色标牌),我希望粉色标牌可以显示在最上层,可偏偏蓝色标牌却将其遮挡住了。于是我对Overlay的层级开始起了兴趣&…...
清晰易懂的 Flutter 卸载和清理教程
以下是为 Flutter 彻底卸载与清理教程,覆盖 Windows、macOS、Linux 系统,步骤清晰无残留,确保完全删除 Flutter SDK、依赖工具及 IDE 配置。 一、通用步骤:确认 Flutter 安装方式 Flutter 通常通过以下方式安装: 手动…...
docker-compose部署以及常用命令
一:常用命令 1.docker compose restart//重启 2.docker compose down// 停止 3.docker compose ps//列出 4.sudo docker-compose up -d 启动并且在后台运行 二:yaml配置文件 version: 3.5 services:etcd:container_name: milvus-etcdimage: quay.io/coreos/etcd:…...
《Golang高性能网络编程:构建低延迟服务器应用》
在本文中,我们将深入探讨Golang高性能网络编程,帮助您构建低延迟服务器应用。我们将介绍Golang的网络编程特性、优化技巧和实际案例,让您更好地理解和应用Golang在网络编程领域的优势。 高性能网络编程简介 什么是Golang高性能网络编程 高性能…...
非对称加密技术深度解析:从数学基础到工程实践
一、密码学范式革命:从对称到非对称 1.1 对称加密的局限性 传统对称加密算法(如AES、DES)采用共享密钥机制,加解密使用相同密钥。虽然计算效率优异(AES-256加密速度可达800MB/s),但在密钥分发环…...
Ubuntu 22.04/24.04 配置apt 源
前言 在 Ubuntu 系统部署与运维中,APT 源配置是保障软件安装效率与系统稳定性的核心环节。然而,随着 Ubuntu 24.04 LTS(Noble)的发布,其 APT 源配置格式与 22.04 LTS(Jammy)存在显著差异。 …...
数据结构C语言练习(设计循环队列)
一、循环队列简介 循环队列是一种线性数据结构,基于 FIFO(先进先出)原则,将队尾连接到队首形成循环。其核心优势是能复用队列之前用过的空间,避免普通队列 “假溢出” 问题。实现时,通常申请 k1 大小的数组…...
vscode代码片段的设置与使用
在 Visual Studio Code (VS Code) 中,可以通过自定义**代码片段(Snippets)**快速插入常用代码模板。以下是详细设置步骤: 步骤 1:打开代码片段设置 按下快捷键 Ctrl Shift P(Windows/Linux)或…...
在Vue中如何高效管理组件状态
在Vue中高效管理组件状态,可以采用以下几种策略: 使用Vuex进行状态管理: 对于复杂的应用,使用Vuex是一个非常有效的状态管理方案。Vuex提供了一个集中存储管理所有组件的状态,并以响应式的方式更新视图。它包括以下几个…...
uniapp -- 列表垂直方向拖拽drag组件
背景 需要在小程序中实现拖拽排序功能,所以就用到了m-drag拖拽组件,在开发的过程中,发现该组件在特殊的场景下会有些问题,并对其进行了拓展。 效果 组件代码 <template><!-- 创建一个垂直滚动视图,类名为m-drag --><scroll...
一款非常小的软件,操作起来非常丝滑!
今天我想给大家分享一款超级实用的小软件,它是一款电脑上用的倒计时和关机助手。 关机助手 帮你自动关机 这款关机助手特别小巧,完全不需要安装,文件大小才60KB,比一个小小的文件还小。你只需要把它下载下来,双击打开…...
FrameWork基础案例解析(四)
文章目录 单独拉取framework开机与开机动画横屏Android.mk语法单独编译SDKmake 忽略warning单独修改和编译Camera2单独编译Launcher3Android Studio 导入、修改、编译Settings导入 Android Studio 导入、修改、编译Launcher3android 开机默认进入指定Launcher植入自己的apk到系…...
嵌入式电量与功耗优化:从理论到实战
目录 一、为什么功耗是个大问题? 电池寿命的命门 效率决定竞争力 运营成本的隐形杀手 环保不是空话 二、功耗从哪来?硬件软件一个都跑不了 硬件:功耗的物理根源 处理器:耗电主力军 存储器:偷偷摸摸的耗电鬼 电源管理单元(PMU):幕后功臣也有损耗 时钟系统:滴…...
通过 C# 提取PDF文档中的图片
当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,避免每次都要从 PDF 中查找。本文将介绍如何使用C#通过代码从PDF文档中提取图片ÿ…...
国标GB28181视频监控平台EasyCVR保驾护航休闲娱乐“九小场所”安全运营
凭借降低人力资源、节约物资成本的优势,在多个场景得到广泛应用。如今,棋牌室、洗浴中心、酒店这类人员频繁流动和密集的场所,已成为安全管理的重点。 尽管部分棋牌室已安装了监控设备,但是设备功能单一,只能实现一…...
GoLand 2024.3 中文 GO语言开发工具
GoLand 2024.3 中文 GO语言开发工具 文章目录 GoLand 2024.3 中文 GO语言开发工具一、介绍二、效果三、下载 一、介绍 JetBrains GoLand 2024 ,是一款GO语言开发工具,全行代码补全:能使用本地运行的上下文感知深度学习模型,可以自…...
HTML 音频(Audio)学习笔记
一、HTML 音频概述 在 HTML 中,音频可以通过多种方式播放,但要确保音频在不同浏览器和设备上都能正常播放,需要掌握一些技巧。HTML5 引入了 <audio> 元素,为音频播放提供了一种标准方法,但在 HTML4 中ÿ…...
去中心化交易所(DEX)
核心概念与DEX类型 DEX vs CEX 中心化交易所(CEX)风险:资产托管风险(如2019年超2.9亿美元被盗)、隐私泄露(如50万用户信息泄漏)。 DEX优势:用户自持资产(非托管&#x…...
CentOS 7 强制升级Docker 24.x终极指南(解决MySQL8镜像兼容性问题)
CentOS 7 强制升级Docker 24.x终极指南(解决MySQL8镜像兼容性问题) 旧版本: 新版本docker: 一、问题背景与方案选型 1.1 典型报错分析 The designated data directory /var/lib/mysql/ is unusable根本原因:旧版…...
【区块链安全 | 第十九篇】类型之映射类型
文章目录 映射类型可迭代映射 映射类型 映射类型使用语法 mapping(KeyType KeyName? > ValueType ValueName?),映射类型的变量声明使用语法 mapping(KeyType KeyName? > ValueType ValueName?) VariableName。 KeyType 可以是任何内置值类型、bytes、st…...
Flask与 FastAPI 对比:哪个更适合你的 Web 开发?
在开发 Web 应用时,Python 中有许多流行的 Web 框架可以选择,其中 Flask 和 FastAPI 是两款广受欢迎的框架。它们各有特色,适用于不同的应用场景。本文将从多个角度对比这两个框架,帮助你更好地选择适合的框架来构建你的 Web 应用…...
QT 中的元对象系统(五):QMetaObject::invokeMethod的使用和实现原理
目录 1.简介 2.原理概述 3.实现分析 3.1.通过方法名调用方法的实现分析 3.2.通过可调用对象调用方法的实现分析 4.使用场景 5.总结 1.简介 QMetaObject::invokeMethod 是 Qt 框架中的一个静态方法,用于在运行时调用对象的成员函数。这个方法提供了一种动态调…...
Linux进程管理与进程间通信
一、进程基础知识 1. 进程的定义与特性 **定义**:进程是程序的一次执行过程,是系统资源分配的基本单位 **特性**: - 动态性:进程是程序的动态执行过程 - 并发性:多个进程可以并发执行 - 独立性:进…...
