Spring-Aop源码解析(二)
书接上文,上文说到,specificInterceptors 不为空则执行createProxy方法创建代理对象,即下图的createProxy方法开始执行,生成代理对象,生成代理对象有两种方式,JDK和CGLIB。
createAopProxy就是决定使用哪种方式生成动态代理对象,方法执行流程和代码如下:
/*** 真正的创建代理,判断一些列条件,有自定义的接口的就会创建jdk代理,否则就是cglib* @param config the AOP configuration in the form of an* AdvisedSupport object* @return* @throws AopConfigException*/@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {// 这段代码用来判断选择哪种创建代理对象的方式// config.isOptimize() 是否对代理类的生成使用策略优化 其作用是和isProxyTargetClass是一样的 默认为false// config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象 默认为false// hasNoUserSuppliedProxyInterfaces目标类是否有接口存在 且只有一个接口的时候接口类型不是SpringProxy类型if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {// 上面的三个方法有一个为true的话,则进入到这里// 从AdvisedSupport中获取目标类 类对象Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}// 判断目标类是否是接口 如果目标类是接口的话,则还是使用JDK的方式生成代理对象// 如果目标类是Proxy类型 则还是使用JDK的方式生成代理对象if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}// 配置了使用Cglib进行动态代理或者目标类没有接口,那么使用Cglib的方式创建代理对象return new ObjenesisCglibAopProxy(config);}else {// 使用JDK的提供的代理方式生成代理对象return new JdkDynamicAopProxy(config);}}
此处使用ObjenesisCglibAopProxy方式
getProxy:168, CglibAopProxy (org.springframework.aop.framework)
创建代理对象方法及注释如下:
/*** 获取cglib的代理对象* @param classLoader the class loader to create the proxy with* (or {@code null} for the low-level proxy facility's default)* @return*/@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {// 从advised中获取ioc容器中配置的target对象Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;//如果目标对象已经是CGLIB 生成代理对象(就是比较类名称中有 $$ 字符串),那么就取目标对象的父类作为目标对象的类if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {proxySuperClass = rootClass.getSuperclass();// 获取原始父类的接口Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.// 打印出不能代理的方法名,CGLIB 是使用继承实现的,所以final , static 的方法不能被增强validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...// 创建及配置EnhancerEnhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 配置超类,代理类实现的接口,回调方法等enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 获取callbacksCallback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.// 通过 Enhancer 生成代理对象,并设置回调return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}
rootClass是需要被代理的对象,Enhancer该类用于生成代理对象,代理如何生成:CGLIB和JDK两种生成方式。
getProxy:168, CglibAopProxy (org.springframework.aop.framework)
getProxy:116, ProxyFactory (org.springframework.aop.framework)
createProxy:519, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
wrapIfNecessary:383, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:319, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:529, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:2273, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:736, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:630, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:417, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 71399214 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$12)
getSingleton:370, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:414, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:260, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:993, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:1024, AbstractApplicationContext (org.springframework.context.support)
refresh:614, AbstractApplicationContext (org.springframework.context.support)
<init>:150, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:87, ClassPathXmlApplicationContext (org.springframework.context.support)
main:15, TestAop (com.mashibing.aop.xml)
一级缓存里是MyCalculator的代理对象 后续执行就是这个代理对象的方法,然后跳转到
intercept:709, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
这个方法
@Override@Nullablepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// 从advised中获取配置好的AOP通知List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.// 如果没有aop通知配置,那么直接调用target对象的调用方法if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);// 如果拦截器链为空则直接激活原方法retVal = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...// 通过cglibMethodInvocation来启动advice通知retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}@Overridepublic boolean equals(@Nullable Object other) {return (this == other ||(other instanceof DynamicAdvisedInterceptor &&this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));}
chain = {ArrayList@2276} size = 6
0 = {ExposeInvocationInterceptor@2242}
1 = {AspectJAfterThrowingAdvice@2282} “org.springframework.aop.aspectj.AspectJAfterThrowingAdvice: advice method [public static void com.mashibing.aop.xml.util.LogUtil.logException(org.aspectj.lang.JoinPoint,java.lang.Exception)]; aspect name ‘logUtil’”
2 = {AfterReturningAdviceInterceptor@2283}
3 = {AspectJAfterAdvice@2284} “org.springframework.aop.aspectj.AspectJAfterAdvice: advice method [public static void com.mashibing.aop.xml.util.LogUtil.logFinally(org.aspectj.lang.JoinPoint)]; aspect name ‘logUtil’”
4 = {AspectJAroundAdvice@2285} “org.springframework.aop.aspectj.AspectJAroundAdvice: advice method [public java.lang.Object com.mashibing.aop.xml.util.LogUtil.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; aspect name ‘logUtil’”
5 = {MethodBeforeAdviceInterceptor@2286}
执行的就是上面6个的通知,通过索引下标挨个执行
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
执行顺序如下:
本文主要讲解springAop如何创建动态代理对象以及使用哪种方式创建的依据;在执行方法跳转到生成的代理对象中,然后生成拦截器链去执行
相关文章:
Spring-Aop源码解析(二)
书接上文,上文说到,specificInterceptors 不为空则执行createProxy方法创建代理对象,即下图的createProxy方法开始执行,生成代理对象,生成代理对象有两种方式,JDK和CGLIB。 createAopProxy就是决定使用哪…...
antdesgin table 组件下载成excel
文章目录 发现宝藏一、需求二、报错 发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。 一、需求 原组件如下,需要添加下载功能 import React, { useState } from rea…...
MongoDB - 聚合阶段 $group 的使用
文章目录 1. 构造测试数据1. 示例 12. 示例23. 示例34. 示例45. 示例5 2. 构造测试数据1. 示例12. 示例23. 示例3 在 MongoDB 中,$group 是聚合管道中的一个阶段,用于根据指定的条件对文档进行分组。 {$group: {_id: <expression>, // 分组的依据…...
Flutter 插件之 easy_refresh(下拉刷新、上拉加载)
今天给大家较少一下日常开发中最常见的一个功能,就是 下拉刷新、上拉加载,这个在我们使用分页功能是最常见的。 此前我我也写了一篇关于 下拉刷新、上拉加载。 Flutter 下拉刷新、上拉加载flutter_easyrefresh的使用https://blog.csdn.net/WangQingLei0307/article/details/…...
DVWA的安装和使用
背景介绍 DVWA是Damn Vulnerable Web Application的缩写,是一个用于安全脆弱性检测的开源Web应用。它旨在为安全专业人员提供一个合法的测试环境,帮助他们测试自己的专业技能和工具,同时也帮助web开发者更好地理解web应用安全防范的过程。DV…...
CSS相关记录
文章目录 backgroundposition文字displayflexjustify-contentalign-itemsflex-directionflex-wrap gridimportant transformtranslate(位移)scale(缩放)rotate(旋转)origin (旋转中心点)skew (倾斜 ) borde…...
Fedora40安装telnet-server启用telnet服务
Fedora40安装telnet-server启用telnet服务 安装 telnet-server sudo yum install telnet-server或 sudo dnf install telnet-server启用服务 fedora40 或 CentosStream9 不能用 yum或dnf安装xinetd, telnet-server 的服务名为: telnet.socket 启用 telnet.socket.service …...
Unity3D结合AI教育大模型 开发AI教师 AI外教 AI英语教师案例
自2022年底ChatGPT引爆全球之后,大模型技术便迎来了一段崭新的快速发展期,由其在GPT4.0发布后,AI与教育领域结合产品研发、已成为教育AI科技竞争的新高地、未来产业的新赛道、经济发展的新引擎和新产品的诞生地。 据不完全统计,目…...
lua 游戏架构 之 SceneLoad场景加载(一)
设计一个为BaseSceneLoad class,用于处理场景加载的相关操作 ,主要作用是提供了一个通用的场景加载框架,使得子类可以按照统一的接口进行场景加载操作。子类需要实现这些方法,以便在加载场景时能够正确地处理场景加载的各个阶段。…...
【linux深入剖析】命名管道 | 匿名管道与命名管道的区别 | system V共享内存
🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1. 命名管道2. 创建命名管…...
Vite 常用插件配置:自动导入+自动注册组件+动态创建图标+设置组件名
创建 Vue3Vite 项目 创建 Vue3 项目 $ pnpm create vuelatest通过脚手架选择开启以下功能 ✔ Project name: … <your-project-name> ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router for Single Page Application development?…...
(leetcode学习)236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖…...
Zabbix监控系统:zabbix服务部署+基于Proxy分布式部署+zabbix主动与被动监控模式
一、Zabbix概述 1.1 简介 zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。 zabbix 能监视各种网络参数,保证服务器系统的安全运营,提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题。 zabbix…...
【Vue实战教程】之 Vue Router 路由详解
Vue Router路由 1 路由基础 1.1 什么是路由 用Vue.js创建的项目是单页面应用,如果想要在项目中模拟出来类似于页面跳转的效果,就要使用路由。其实,我们不能只从字面的意思来理解路由,从字面上来看,很容易把路由联想…...
测试用例接口开发实战
测试用例接口开发实战 前言 在上一集,我们也大概完成了对Jmeter的二次开发的Demo版本的了解,我们接下来就要基于这个Demo来将Jmeter压测进行平台化。 那么这一集,我们讲一讲测试用例接口开发实战。 StressCaseController 我们的Controll…...
C#中压缩文件夹,及其内容
压缩包格式,本文主要用于说明如何使用代码 文件或文件夹压缩为 zip压缩包及其解压操作, 下面分两个版本进行实现 1.简单版本 bool DoCompressDirectoryInfo(string folderPath){try{var zipFilePath $"{folderPath}.zip";var directoryInfo …...
机器学习 | 回归算法原理——多项式回归
Hi,大家好,我是半亩花海。接着上次的最速下降法(梯度下降法)继续更新《白话机器学习的数学》这本书的学习笔记,在此分享多项式回归这一回归算法原理。本章的回归算法原理基于《基于广告费预测点击量》项目,…...
力扣224【基本计算器】
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。 注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。 1 < s.length < 3 * 105 s 由数字、‘’、‘-’、‘(’、‘)’、和 ’ ’ 组成 s 表示一个有效的…...
【Linux】HTTP 协议
目录 1. URL2. HTTP 协议2.1. HTTP 请求2.2. HTTP 响应 1. URL URL 表示着是统一资源定位符(Uniform Resource Locator), 就是 web 地址,俗称“网址”; 每个有效的 URL 可以通过互联网访问唯一的资源, 是互联网上标准资源的地址; URL 的主要由四个部分组成: sche…...
@Builder注释导致@RequestBody的前端json反序列化失败,HTTP400
项目里发生了一个bug,就是前端请求一个接口时候,报了HTTP 400 Bad Request 通常来说这个问题是前后端的参数没对齐,比如前端传了个String,但后端对应的是Integer。 所以我就排查了半天,结果没发现啥错误,…...
网络学习|如何理解服务的端口号
文章目录 1. 端口号的定义2. 端口号的分类3. 端口号的用途4. 注意事项5. 示例图解 后端面试中可能遇到的端口相关问题及答案1. 什么是端口号?为什么需要端口号?2. 知名端口(Well-Known Ports)有哪些,举例说明ÿ…...
《0基础》学习Python——第十八讲__爬虫/<1>
一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序(通常使用Python),爬虫可以自动化地访问网页,解析网页内容并提取出所需的数据。爬虫可以用于各种用途,如搜索引擎的索引,数据分析和挖掘&#x…...
NFTScan 浏览器现已支持 .mint 域名搜索功能!
近日,NFT 数据基础设施 NFTScan 浏览器现已支持用户输入 .mint 域名进行 Mint Blockchain 网络钱包地址的搜索查询, NFTScan 用户能够轻松地使用域名追踪 NFT 交易,为 NFT 钱包地址相关的搜索查询功能增加透明度和便利性。 NFTScan explorer…...
Git基本原理讲解、常见命令、Git版本回退、Git抛弃本地分支拉取仓库最新分支
借此机会写篇博客汇总一下自己去公司实习之后遇到的一些常见关于Git的操作。 Git基本认识 Git把数据看作是对小型文件系统的一组快照,每次提交更新,或在Git中保存项目状态时,Git主要对当时的全部文件制作一个快照并保存这个快照的索引。同时…...
前端网页打开PC端本地的应用程序实现方案
最近开发有一个需求,网页端有个入口需要跳转三维大屏,而这个大屏是一个exe应用程序。产品需要点击这个入口,并打开这个应用程序。这个就类似于百度网盘网页跳转到PC端应用程序中。 这里我们采用添加自定义协议的方式打开该应用程序。一开始可…...
遇到not allow unquoted fieldName怎么办
前言 Exception in thread "main" com.alibaba.fastjson2.JSONException: not allow unquoted fieldName, offset 2, character , line 1, column 3, fastjson-version 2.0.25 { "data":null, "code":200, "msg":"成功"…...
IDEA安装并使用通义灵码
IDEA安装并使用通义灵码 通义灵码介绍安装通义灵码 通义灵码介绍 在数字革命的前沿,阿里云技术团队匠心独运,倾力打造“通义灵码”——一个融合尖端科技的智能编码助手,旨在革新软件工程的未来。 实时代码扩展 通义灵码具备深度理解代码脉络的…...
<数据集>AffectNet表情识别数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:29752张 标注数量(xml文件个数):29752 标注数量(txt文件个数):29752 标注类别数:7 标注类别名称:[anger,contempt,disgust,fear,happy,neutral,sad,surprise] 序号类…...
ThinkPHP对接易联云打印
引入composer包 composer require yly-openapi/yly-openapi-sdk <?phpnamespace app\common\library;use app\admin\model\yp\Order; use App\Api\PrintService; use App\Config\YlyConfig; use App\Oauth\YlyOauthClient; use think\Cache; use think\Config;class Yly {…...
JavaScript轮播图
HTML部分 <div class"box" onmouseover"over()" onmouseout"noover()"><img src"./img/zuo.png" alt"" class"left_arrow" onclick"left_last()"><img src"./img/yy.png" al…...
修复SteamUI.dll加载失败的指南,快速修复failed to load steamui.dll
在使用Steam平台进行游戏下载、安装和运行时,可能会遇到一些系统错误,比如“failed to load steamui.dll”。这个错误通常意味着Steam的用户界面库文件steamui.dll出现了问题。本文将详细介绍steamui.dll文件的相关信息以及如何修复这一问题。 一.什么是…...
PCL Local Surface Patches 关键点提取
目录 一、算法原理1、算法原理2、 参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、算法原理 主曲率是某一点局部形状的体现,Local Surface Patches 关键点检测法…...
Vue与ASP.NET Core Web Api设置localhost与本地ip地址皆可访问
Vue的设置 我们创建并启动一个Vue项目,如下所示: 打开cmd,输入ipconfig查询本地ip地址: 想通过本地ip地址访问,把localhost改成本地ip地址,发现打不开: 这是因为Vue项目默认只有localhost&…...
Android 线程池的面试题 线程线程池面试题
1.为什么要用线程池 降低资源消耗:通过复用线程,降低创建和销毁线程的损耗。 提高响应速度:任务不需要等待线程创建就能立即执行。 提高线程的可管理性:使用线程池可以进行统一的分配、调优和监控。 2. 线程池执行流程(…...
Flink时间和窗口
目录 时间语义 水位线(Watermarks) 并行流中的水位线 窗口 滚动窗口—Tumbling Windows 滑动窗口—Sliding Windows 会话窗口—Session Windows 全局窗口—Global Windows 例子 时间语义 如图所示,由事件生成器(Event Pr…...
LLaMA模型量化方法优化:提高性能与减小模型大小
LLaMA模型量化方法优化:提高性能与减小模型大小 LLaMA模型量化方法优化:提高性能与减小模型大小引言新增量化方法性能评估7B模型13B模型 结果分析结论 LLaMA模型量化方法优化:提高性能与减小模型大小 引言 在大型语言模型(LLM)的应用中,模型大小和推理速度一直是关键的挑战。…...
前端CSS实现卡片抽奖效果
引言 在网页设计中,互动元素能够显著提升用户体验,吸引用户的注意力。其中,卡片抽奖效果常用于营销活动、游戏或娱乐场景,通过随机展示不同的卡片来增加趣味性和参与度。本文将详细介绍如何使用HTML和CSS来实现一个简单的卡片抽奖…...
Java在for循环中修改集合
前天看到一篇文章什么?for循环也会出问题?,里面涉及到在for循环中修改集合,想起来自己刚入行的时候就碰到过类似的问题,于是复现了一下文章中的问题,并试验了其它在循环中修改集合的方法。 底层原理参考什…...
Java小白入门到实战应用教程-运算符详解
Java小白入门到实战应用教程-运算符 上节回顾 在上节的内容中我们了解了变量和基本数据类型的内容,现在回顾一下上节课的内容。 声明变量的语法为: 数据类型 变量名; 其中在java中一共有8中基本数据类型,分别是:b…...
secureCRT同时在所有已打开窗口执行命令、mac-os下使用的SecureCRT版本 以及 SecureCRT一段时间不操作没有响应的问题
一、secureCRT命令行工具一次性同时在所有已打开窗口执行命令 公司的服务器比较多,最近因为opcache,上线发布后,需要重启所有的WEB服务器上的php。目前使用的jenkins发布,不过账号安全问题,给jenkins的账号权限受限不能…...
增材制造与智能制造关系
在撰写的增材制造技术与装备书籍中有着明确的描述,增材制造是智能制造的典型范例,是智能制造“类”的实例化过程。这种借助于计算机编程面向对象思想的解释可以更全面的理解增材制造和智能制造的关系。增材制造实例具备了智能制造类的属性,智…...
Google Test 学习笔记(简称GTest)
文章目录 一、介绍1.1 介绍1.2 教程 二、使用2.1 基本使用2.1.1 安装GTest (下载和编译)2.1.2 编写测试2.1.3 运行测试2.1.4 高级特性2.1.5 调试和分析 2.2 源码自带测试用例2.3 TEST 使用2.3.1 TestCase的介绍2.3.2 TEST宏demo1demo2 2.3.3 TEST_F宏2.3…...
不可变集合
定义:就是集合中的内容不可以被修改。 如何获取不可变集合? List、Set、Map类中提供的静态方法of可用来获取不可变集合。 特点:一旦创建完成只可以进行查询,不可以增删改。 细节:Map集合中的of方法只能添加10个键值…...
景区AR导航营销系统:技术解决方案与实施效益分析
随着旅游市场的竞争日益激烈,景区需要不断创新以吸引游客。景区 AR 导航将虚拟画面与现实场景相结合,为游客提供了更加直观、生动的导航服务。对于景区而言,这一创新技术无疑是吸引游客目光、提升景区知名度的有力武器。通过独特的 AR 导航体…...
MATLAB的基础知识
matlab的基本小常识 1. 在每行语句后面加上英文分号表示不在命令行窗口显示运行结果。 a 3; a 5 2. 多行注释快捷键,CTRLR。 3. 取消多行注释,CTRLT。 4. 清空工作区的所有变量使用clear。 5. 清空命令行窗口的所有变量使用clc。 6. clc和clear一起使…...
Redis-高级实战案例
文章目录 Redis集群崩溃时如何保证秒杀系统高可用1. 冗余与备份2. 故障检测与自动切换3. 降级策略4. 数据一致性5. 客户端缓存6. 异常处理与通知7. 测试与演练8. 服务降级与回滚Redis主从切换导致库存同步异常以及超卖问题主从切换导致的库存同步异常原因:解决方案:秒杀链路中…...
d3d12.dll 文件缺失如何解决?五种修复丢失问题的方法
d3d12.dll 文件缺失如何解决?它为什么会不见呢?今天,我们将探讨 d3d12.dll 文件的重要性、原因以及丢失时的解决策略。本文将全面介绍 d3d12.dll 文件,并提供五种修复丢失问题的方法。 d3d12.dll文件是什么的详细介绍 d3d12.dll …...
Linux下如何设置系统定时任务
在Linux系统中,用户可以使用cron工具来设置定时任务。cron是一个守护进程,用于在指定的时间间隔执行指定的命令或脚本。下面是在Linux系统中设置系统定时任务的步骤。 使用crontab命令编辑定时任务列表: crontab -e该命令会打开一个文本编辑…...
【React】JSX 实现列表渲染
文章目录 一、基础语法1. 使用 map() 方法2. key 属性的使用 二、常见错误和注意事项1. 忘记使用 key 属性2. key 属性的选择 三、列表渲染的高级用法1. 渲染嵌套列表2. 条件渲染列表项3. 动态生成组件 四、最佳实践 在 React 开发中,列表渲染是一个非常常见的需求。…...
写一个简单的兼容GET/POST请求的登录接口
本文目录 安装JDK17安装或者更新Intelij Idea 2024SpringBoot生成项目压缩包下载maven,idea添加maven写POST接口浏览器访问GET接口PostMan安装及访问POST接口 安装JDK17 参考:https://blog.csdn.net/tiehou/article/details/129575138 安装或者更新Int…...