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

《深入理解 AOP》

一、AOP 是什么

AOP(Aspect Oriented Programming),即面向切面编程,是软件开发中一种重要的编程范式。它通过横向抽取机制,将那些与业务逻辑本身无关、却为业务模块所共同调用的逻辑或责任(如事务处理、日志管理、权限校验等)封装起来,然后通过“动态植入”的方式嵌入到业务逻辑的指定位置,从而实现业务逻辑的隔离与解耦。

AOP 是面向对象编程(OOP)的补充。在 OOP 中,我们通过类和继承来组织代码,但在某些情况下,会遇到一些问题。例如,当需要为多个不具有继承关系的对象添加公共方法时,如日志记录、性能监控等,如果采用 OOP 的方式,就需要在每个对象中都添加相同的方法,这会导致大量的重复代码,增加维护成本。而 AOP 则可以很好地解决这个问题,它将这些公共逻辑抽取出来,集中管理,避免了重复代码的产生。

二、AOP 的优势

  1. 减少重复代码:将公共逻辑集中到切面中,避免了在多个地方重复编写相同的代码。

  2. 提高开发效率:开发者可以专注于业务逻辑的实现,而无需在每个地方都处理那些公共的、与业务逻辑无关的逻辑。

  3. 方便维护:当需要修改公共逻辑时,只需修改切面中的代码,而无需修改每个使用该逻辑的地方。

三、AOP 的技术要点

(一)通知(Advice)

通知定义了“什么时候”和“做什么”。它包含了需要用于多个应用对象的横切行为。根据通知的执行时机,可以分为以下几种类型:

  1. 前置通知(@Before):在目标方法调用之前调用通知。

  2. 后置通知(@After):在目标方法完成之后调用通知。

  3. 环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法。需要注意的是,目标对象的方法需要手动执行。

  4. 返回通知(@AfterReturning):在目标方法成功执行之后调用通知。

  5. 异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知。

(二)连接点(Join Point)

连接点是程序执行过程中能够应用通知的所有点。在 Spring 中,连接点指的是方法,因为 Spring 只支持方法类型的连接点。

(三)切点(Pointcut)

切点定义了在“什么地方”进行切入,哪些连接点会得到通知。切点表达式用于明确指定方法的返回类型、类名、方法名和参数名等与方法相关的部件。常用的切点表达式格式为:execution([修饰符] 返回值类型 包名.类名.方法名(参数))。其中,修饰符可以省略,返回值类型、包名、类名、方法名和参数都可以使用通配符(*..)来表示。

(四)切面(Aspect)

切面是通知和切点的结合。通知和切点共同定义了切面的全部内容——是什么、何时、何地完成功能。

(五)引入(Introduction)

引入允许我们向现有的类中添加新方法或者属性。

(六)织入(Weaving)

织入是把切面应用到目标对象并创建新的代理对象的过程。织入分为编译期织入、类加载期织入和运行期织入。

四、AOP的底层原理

一、AOP 的底层原理概述

在 Spring 框架中,AOP 的实现依赖于动态代理技术。动态代理技术允许在运行时动态地创建代理对象,并在代理对象上调用方法时插入额外的逻辑(即通知)。Spring AOP 主要使用两种动态代理技术:JDK 动态代理和 CGLIB 代理。

二、JDK 动态代理技术

JDK 动态代理是 Java 提供的一种标准代理机制,它依赖于 Java 的反射机制。JDK 动态代理的核心是 java.lang.reflect.Proxy 类和 InvocationHandler 接口。以下是 JDK 动态代理的实现步骤:

(一)为接口创建代理类的字节码文件

  1. 定义接口:首先,需要定义一个接口,目标对象和代理对象都将实现这个接口。例如:

    public interface UserService {void save();
    }
  2. 实现目标类:目标类实现了上述接口,并提供了具体的业务逻辑。例如:

     
    public class UserServiceImpl implements UserService {@Overridepublic void save() {System.out.println("业务层:保存用户...");}
    }
  3. 创建代理类:通过 java.lang.reflect.Proxy 类动态生成代理类。代理类实现了与目标类相同的接口,并在方法调用时插入额外的逻辑。例如:

    public class MyInvocationHandler implements InvocationHandler {private final Object target;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在目标方法执行前插入逻辑System.out.println("前置通知:记录日志");// 执行目标方法Object result = method.invoke(target, args);// 在目标方法执行后插入逻辑System.out.println("后置通知:记录日志");return result;}
    }
  4. 生成代理实例:通过 Proxy.newProxyInstance 方法动态生成代理实例。例如:

    UserService userService = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), // 目标类的类加载器new Class<?>[]{UserService.class}, // 目标类实现的接口new MyInvocationHandler(new UserServiceImpl()) // 自定义的 InvocationHandler
    );

(二)使用 ClassLoader 将字节码文件加载到 JVM

  1. 类加载器的作用ClassLoader 负责加载字节码文件到 JVM 中。在 JDK 动态代理中,Proxy.newProxyInstance 方法会使用目标类的类加载器来加载生成的代理类。

  2. 动态生成字节码Proxy 类会在运行时动态生成代理类的字节码,并通过类加载器加载到 JVM 中。代理类的字节码是基于目标类实现的接口动态生成的。

(三)创建代理类实例对象,执行对象的目标方法

  1. 代理类实例:通过 Proxy.newProxyInstance 方法生成的代理类实例对象,可以像普通对象一样调用接口方法。

  2. 方法调用:当调用代理类实例的方法时,实际上会调用 InvocationHandlerinvoke 方法。在 invoke 方法中,可以插入前置通知、后置通知等逻辑,并最终调用目标方法。

三、CGLIB 代理技术

CGLIB(Code Generation Library)是一个强大的字节码生成库,它可以在运行时动态生成目标类的子类,并覆盖目标类的方法。CGLIB 代理主要用于那些没有实现接口的类,或者需要代理类的方法而不是接口的方法。

(一)CGLIB 代理的基本原理

  1. 动态生成子类:CGLIB 通过字节码操作库(如 ASM)动态生成目标类的子类。生成的子类继承了目标类,并覆盖了目标类的方法。

  2. 方法拦截:在覆盖的方法中,CGLIB 提供了一个 MethodInterceptor 接口,用于拦截方法调用。在拦截器中,可以插入额外的逻辑,并最终调用目标方法。

(二)CGLIB 代理的实现步骤

  1. 定义目标类:目标类不需要实现接口,例如:

    public class UserServiceImpl {public void save() {System.out.println("业务层:保存用户...");}
    }
  2. 创建拦截器:实现 MethodInterceptor 接口,定义拦截逻辑。例如:

     
    public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 在目标方法执行前插入逻辑System.out.println("前置通知:记录日志");// 执行目标方法Object result = proxy.invokeSuper(obj, args);// 在目标方法执行后插入逻辑System.out.println("后置通知:记录日志");return result;}
    }
  3. 生成代理实例:通过 Enhancer 类动态生成代理实例。例如:

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(UserServiceImpl.class); // 设置目标类
    enhancer.setCallback(new MyMethodInterceptor()); // 设置拦截器
    UserServiceImpl userService = (UserServiceImpl) enhancer.create();
  4. 使用代理实例:通过代理实例调用方法时,实际上会调用拦截器的 intercept 方法,在其中插入额外的逻辑,并最终调用目标方法。

四、JDK 动态代理与 CGLIB 代理的比较

表格
特性JDK 动态代理CGLIB 代理
适用场景目标类必须实现接口目标类可以没有接口
代理方式通过接口代理通过生成子类代理
性能相对较好,因为基于接口调用稍差,因为需要生成子类并覆盖方法
灵活性只能代理接口方法可以代理类的方法,更灵活
实现机制基于 Java 反射和 InvocationHandler基于字节码操作库(如 ASM)

相关文章:

《深入理解 AOP》

一、AOP 是什么 AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff0c;即面向切面编程&#xff0c;是软件开发中一种重要的编程范式。它通过横向抽取机制&#xff0c;将那些与业务逻辑本身无关、却为业务模块所共同调用的逻辑或责任&#xff08;如事务处理、日…...

2022李宏毅老师机器学习课程笔记

机器学习笔记目录 1.绪论&#xff08;内容概述&#xff09;2.机器学习和深度学习的基本概念transformer 1.绪论&#xff08;内容概述&#xff09; 机器学习&#xff1a;让机器找一个函数&#xff0c;通过函数输出想要的结果。应用举例&#xff1a;语音识别&#xff0c;图像识别…...

时序数据库IoTDB在航空航天领域的解决方案

在快速发展的航空航天领域&#xff0c;高效、安全的数据管理成为了技术创新和持续发展的关键支撑。时序数据库IoTDB&#xff0c;凭借其国产自研、高效低流量数据同步、丰富的部署选择等优势&#xff0c;为航空航天产业提供了强有力的数据基础&#xff0c;助力产业加速转型升级。…...

洛谷 B3647:【模板】Floyd 算法

【题目来源】 https://www.luogu.com.cn/problem/B3647 【题目描述】 给出一张由 n 个点 m 条边组成的无向图。 求出所有点对 (i,j) 之间的最短路径。 【输入格式】 第一行为两个整数 n&#xff0c;m&#xff0c;分别代表点的个数和边的条数。 接下来 m 行&#xff0c;每行三…...

【25软考网工】第三章(4)生成树协议、广播风暴和MAC地址表震荡

目录 一、生成树协议1. 生成树技术背景1&#xff09;单链路上行存在单点故障2&#xff09;二层环路问题3&#xff09;二层环路问题——广播风暴实验验证 广播风暴例题1&#xff1a;二层环路故障现象4&#xff09;二层环路问题—— MAC地址表震荡实验验证 MAC地址表震荡的现象 2…...

解释器体系结构风格-笔记

解释器&#xff08;Interpreter&#xff09;是一种软件设计模式或体系结构风格&#xff0c;主要用于为语言&#xff08;或表达式&#xff09;定义其语法、语义&#xff0c;并通过解释器来解析和执行语言中的表达式。解释器体系结构风格广泛应用于编程语言、脚本语言、规则引擎、…...

删除新安装IBM Guardium Data Protection 12.1的baltimorecybertrustroot证书

登录web console&#xff0c;会显示 baltimorecybertrustroot证书过期警告。 采用下面的命令删除过期证书就可消除警告。 collector02.cpd.com> delete certificate keystore Select an alias from the list below to delete the corresponding certificate. Alias List:…...

反序列化漏洞1

一、PHP类与对象 1. 类 概念理解: 类是共享相同结构和行为的对象的集合&#xff0c;可以理解为特征的提取。例如将耳朵长、尾巴短、红眼睛、吃胡萝卜、蹦跳行走的动物特征抽象为"兔子"类。代码结构: 使用class关键字定义类类名遵循大驼峰命名法包含成员变量(属性)和…...

正则表达式三剑客之——awk命令

目录 一.什么是awk 二.awk的语法格式 1.选项 2. 模式&#xff08;Pattern&#xff09; 3. 操作&#xff08;Action&#xff09; 4. 输入文件&#xff08;file&#xff09; 5.总结 三.awk的工作原理 1. 逐行扫描输入 2. 匹配模式 1.正则表达式&#xff1a; 2.逻辑表…...

施磊老师基于muduo网络库的集群聊天服务器(七)

文章目录 数据表字符集问题支持中文和英文**为什么使用 utf8mb4&#xff1f;** 推荐 查看整个表, 再单独修改 客户端群组功能创建群组添加群组群组聊天接收在线群组消息接收离线群组消息补充服务器事件处理器补充服务器查询群组列表问题解决测试 目前报错总结目前为止最恶心的错…...

多模态(3):实战 GPT-4o 视频理解

最近&#xff0c;OpenAI 团队的 GPT-4o 模型&#xff0c;在多模态方面的能力有了大幅提升&#xff0c;这次我们就使用 GPT-4o 完成一个视频理解的实战。 1. 环境搭建 1.1 安装 FFmpeg 做视频处理&#xff0c;我们需要用到 FFmpeg 这款功能强大的开源多媒体处理工具。FFmpeg…...

基于python实现一个二维图片的路径规划问题

一、场景 基于如下的一个楼层平面图&#xff0c;假设有几个预置的点&#xff08;实际项目中可能是动态的点&#xff0c;比如找车位&#xff0c;找工位&#xff09;&#xff0c;做路径规划&#xff0c;并画在平面图上 二、方案 1.准备平面室内图 可以自己用QGIS/cad等其他方式…...

云服务器centos 安装hadoop集群

百度 搜索 云服务器centos 安装hadoop 创建Hadoop用户 sudo useradd hadoop -m -s /bin/bash sudo passwd hadoop 123456 下载Hadoop wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.2.4/hadoop-3.2.4.tar.gz 解压并移动Hadoop到指定目录 tar …...

【k8s】sidecar边车容器

一、Sidecar 模式简介 Sidecar 模式是一种常见的微服务架构设计模式。它通过将附加功能或服务与主应用程序部署在同一容器或主机上&#xff0c;从而实现对主应用程序的增强和扩展。Sidecar 的名称来源于摩托车的边车&#xff0c;它与摩托车紧密相连&#xff0c;为主车提供额外…...

Web漏洞--XSS之订单系统和Shell箱子

本文主要内容 手法 XSS平台使用 XSS工具使用 XSS结合其他漏洞 XSS具体使用场景 某订单系统XSS盲打_平台 某Shell箱子系统XSS盲打_工具 [1]订单系统经典案例 第一个简易攻击流程&#xff08;订单系统&#xff09;&#xff1a;通过平台完成XSS跨站之后&a…...

# 构建词汇表:自然语言处理中的关键步骤

构建词汇表&#xff1a;自然语言处理中的关键步骤 在自然语言处理&#xff08;NLP&#xff09;任务中&#xff0c;词汇表&#xff08;Vocabulary&#xff09;是文本数据预处理的核心组件之一。它将文本中的单词或字符映射为数值索引&#xff0c;从而让计算机能够理解和处理语言…...

新!在 podman-machine-default 中安装 CUDA、cuDNN、Anaconda、PyTorch 等并验证安装

#工作记录 一、前言 在 Windows 系统开发环境中&#xff0c;Podman Desktop 凭借强大的容器管理与 WSL-Linux 子系统集成能力备受开发者关注。 其中&#xff0c;podman-machine-default 是 Podman Desktop 安装后自带的默认 WSL-Fedora 子系统&#xff0c;支持与显卡通信&am…...

python_BeautifulSoup提取html中的信息

目录 描述&#xff1a; 过程&#xff1a; step one 下载html网页到本地 step two 提取html信息 list_con soup.select(.list-con) [0] li_list list_con.find_all(li) a li.find(span).find(a) title a.get(title) url a.get(href) span li.find(span).find(spa…...

pcd2pgm的launch文件实现

1.新建工作空间和克隆代码 mkdir -p pcd2pgm_launch/src && cd pcd2pgm_launch/src git clone https://github.com/Hinson-A/pcd2pgm_package 2. 编译 cd .. catkin_make -j4 3.修改launch 在launch文件目录下&#xff0c;可以用gedit 打开launch文件&#xff0c…...

Vue里面elementUi-aside 和el-main不垂直排列

先说解决方法 main.js少导包 import element-ui/lib/theme-chalk/index.css; //加入此行即可 问题复现 排查了一个小时终于找出来问题了&#xff0c;建议导包去看官方的文档&#xff0c;作者就是因为看了别人的导包流程导致的问题 导包官网地址Element UI导包快速入门...

论文阅读:2024 ACL ArtPrompt: ASCII Art-based Jailbreak Attacks against Aligned LLMs

总目录 大模型安全相关研究&#xff1a;https://blog.csdn.net/WhiffeYF/article/details/142132328 Artprompt: Ascii art-based jailbreak attacks against aligned llms https://www.doubao.com/chat/3846685176618754 https://arxiv.org/pdf/2402.11753 https://github…...

项目maven版本不一致 导致无法下载

路程&#xff1a;打开一个新项目发现&#xff0c;maven加载不了 报错&#xff1a; Error running ‘dataManage [clean]’ No valid Maven installation found. Either set the home directory in the configuration dialog or set the M2_HOME environment variable on your s…...

论文阅读:2024 NeurIPS Group Robust Preference Optimization in Reward-free RLHF

Group Robust Preference Optimization in Reward-free RLHF https://www.doubao.com/chat/3870738843518978 https://arxiv.org/pdf/2405.20304 速览 研究动机 传统RLHF忽视群体偏好差异&#xff0c;导致模型对少数群体表现不佳&#xff0c;需提升群体鲁棒性。研究问题 如…...

数据可视化平台产品介绍及功能特色

数据可视化平台是一款适用于高校教学和各领域企业的零门槛可视化工具&#xff0c;能够解决高校数据分析与可视化类课程教学、实训问题。平台通过浏览器即可访问&#xff0c;无需安装客户端。平台内置公式编辑器与指标构建器&#xff0c;学生可通过四则运算、分组聚合等方式衍生…...

MySQL索引优化、SQL分析与运行原理 - Java架构师面试实战

MySQL索引优化、SQL分析与运行原理 - Java架构师面试实战 第一轮提问 面试官&#xff1a;马架构&#xff0c;请问您对MySQL的B树索引有什么理解&#xff1f; 马架构&#xff1a;B树是一种平衡多路查找树&#xff0c;所有的数据节点都存储在叶子节点上。相比于B树&#xff0c…...

C++学习:六个月从基础到就业——STL:函数对象与适配器

C学习&#xff1a;六个月从基础到就业——STL&#xff1a;函数对象与适配器 本文是我C学习之旅系列的第二十九篇技术文章&#xff0c;也是第二阶段"C进阶特性"的第八篇&#xff0c;主要介绍C STL中的函数对象与适配器。查看完整系列目录了解更多内容。 引言 在前面的…...

Linux基础篇、第四章_02磁盘及分区管理fdisk 和 gdisk

题目&#xff1a;Linux 磁盘及分区管理 版本号: 1.0,0 作者: 老王要学习 日期: 2025.04.25 适用环境: Centos7 文档说明 本教程适用于 Centos7 环境&#xff0c;详细介绍 Linux 磁盘及分区管理操作。包含虚拟机添加磁盘的关机与开机添加方法、MBR 和 GPT 两种分区方式特点、…...

火山云的市场竞争

火山云是字节跳动旗下的云计算服务&#xff0c;对吧&#xff1f;那它的竞争对手应该包括国内外的大型云服务提供商。首先&#xff0c;国际市场上&#xff0c;像AWS、Azure、Google Cloud这些巨头肯定是大头。国内的话&#xff0c;阿里云、腾讯云、华为云这些应该都是主要的竞争…...

创建型设计模式之:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式

创建型设计模式之&#xff1a;简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式 &#xff08;一&#xff09;简单工厂模式 简单工厂模式将对象的实例化过程封装到一个工厂类中&#xff0c;根据输入的条件创建不同类型的对象。 角色划分&#xff1a; 抽象产品…...

【Linux内核设计与实现】第三章——进程管理01

文章目录 1. 引言2. 进程&线程——概念3. 进程控制块/进程描述符(PCB)4. 进程内核栈&#xff08;Kernel Stack&#xff09;4.1. 进程内核栈的定义4.2. thread_info 体系结构相关进程描述4.3. 定位进程描述符(task_struct)和内核栈以及内核栈指针的问题 5. 进程 ID&#xff…...

正大模型视角下的市场结构判断逻辑

正大模型视角下的市场结构判断逻辑 在多数交易策略中&#xff0c;结构识别往往先于方向判断。以正大的数据研判风格为例&#xff0c;其核心逻辑是&#xff1a;价格行为不能孤立解读&#xff0c;必须结合时间与成交效率来判断当前结构的有效性。 例如&#xff0c;一个上涨过程&…...

4.25学习——文件上传之00截断

继昨天学习的基础文件上传内容&#xff0c;进一步学习文件上传的绕过方式 00截断绕过 原理&#xff1a;00截断是操作系统层的漏洞&#xff0c;由于操作系统是C语言或汇编语言编写的&#xff0c;这两种语言在定义字符串时&#xff0c;都是以\0&#xff08;即0x00&#xff09;作…...

黑马Redis(三)黑马点评项目

优惠卷秒杀 一、全局唯一ID 基于Redis实现全局唯一ID的策略&#xff1a; Component RequiredArgsConstructor public class RedisIdWorker {private static final Long BEGIN_TIMESTAMP1713916800L;private static final int COUNT_BITS 32;Resourceprivate final StringRed…...

dedecms织梦arclist标签noflag属性过滤多个参数

织梦dedecms系统arclist标签noflag属性默认是只能过滤一个参数&#xff0c;比如过滤推荐是noflagc&#xff0c;过滤有图片的文章是noflagc&#xff0c;在模板制作过程中&#xff0c;有时候我们为了seo和避免重复&#xff0c;需要过滤多个参数。今天小编就来跟大家讲讲织梦dedec…...

Jira、PingCode、Redmine等18款缺陷管理工具对比评测

本文主要介绍了以下&#xff1a;1. PingCode; 2. Worktile; 3. Jira; 4. Bugzilla; 5. TAPD; 6. 码云; 7. Redmine; 8. Trac; 9. 蓝鲸智云; 10. 阿里云效等等18款缺陷管理工具。 在现代软件开发和项目管理中&#xff0c;缺陷管理工具扮演着至关重要的角色。随着企业对软件质量的…...

京东以图搜图(拍立淘)API接口返回参数详解

京东以图搜图&#xff08;拍立淘&#xff09;API接口的返回参数通常以结构化JSON格式呈现&#xff0c;涵盖商品基础信息、相似度评分、库存状态及扩展字段&#xff0c;以下为关键参数详解及使用建议&#xff1a; 一、核心返回参数解析 状态标识类 status&#xff1a;请求状态…...

LSTM+KNN - 多元数据异常检测 !

大家好!我是我不是小 upper~ 今天想和大家分享一个超实用的案例:如何通过 LSTM 与 KNN 实现多元数据异常检测。 想象一下,在工厂的智能化监控场景中,各类传感器实时采集着温度、湿度、压力等海量数据。我们的目标,就是从中精准识别出设备潜在故障等异常情况。 LSTM 作为时…...

OpenHarmony之电源管理子系统公共事件定义

OpenHarmony之电源管理子系统公共事件定义 电源管理子系统面向应用发布如下系统公共事件&#xff0c;应用如需订阅系统公共事件&#xff0c;请参考公共事件接口文档。 COMMON_EVENT_BATTERY_CHANGED 表示电池充电状态、电平和其他信息发生变化的公共事件的动作。 值&#x…...

angular 实现可编辑可选择复制的表格

这个实现的核心就是ag-grid 当然有类似的库就不必多说&#xff0c;React, Vue和纯h5类似。简单贴一下代码 1.首先是h5部分&#xff0c;就一个id为supply-chain-material-grid-table的div&#xff0c;记住要设置高度 <div class"dki-supply-chain-page-body">…...

组织用户数统计实现

# 完整的组织用户数统计实现 完整的组织用户数统计实现&#xff0c;包括模拟SQL查询、完整的Java代码实现以及详细解释。 ## 1. 模拟SQL查询 假设我们有一个组织表(organization)和用户表(user)&#xff0c;以下是模拟查询SQL&#xff1a; sql -- 获取各组织及其用户数量&a…...

天机学堂day10作业,完善兑换优惠券功能

UserCouponServiceImpl /*** 兑换码兑换优惠券* param code*/TransactionalOverridepublic void exchangeCoupon(String code) {//1、校验code是否为空if (StringUtils.isBlank(code)) {throw new BadRequestException("非法参数&#xff01;");}//2、解析兑换码&…...

Python编程的真谛:超越语法,理解编程本质

你是否也曾陷入这样的误区&#xff1a;学了无数的 Python 语法、刷了几十套题&#xff0c;写起代码却仍然卡顿、举步维艰&#xff1f;这时候你才发现&#xff0c;真正阻碍进步的&#xff0c;从不是语法&#xff0c;而是你对“编程本质”的理解。 如果你只是死记硬背Python的语…...

C语言 函数补充

目录 static和extern函数 1.static和extern函数 static和extern都是C语言中的关键字 static 是 静态的 的意思&#xff0c;可以用来: - 修饰局部变量- 修饰全局变量- 修饰函数 extern 是用来声明外部符号的。 在讲解 static 和 extern 之前再讲一下: 作用域和生命周期。 …...

【AI图像创作变现】04实操路径—插图/绘本/创意图集

引言 如果说头像是“一个角色的起点”&#xff0c;那么插图、绘本和图集就是“这个角色能走多远”。相比于头像这种单图任务&#xff0c;插图类创作更强调批量性、叙事性与风格统一性&#xff0c;它既可以承载故事&#xff0c;也可以构成一套完整的内容产品结构。 这类任务特…...

Lesar: 面向 Lustre/Scade 语言的形式化模型检查工具

在《同步反应式系统》的第一课中&#xff0c;介绍了同步数据流语言 Lustre 生态中的形式化模型检查器 Lesar 的用法。Lesar 可对 lustre v4 语言以及 Scade 语言中部分数据流核心特性进行模型检查。 Lesar 介绍 Lesar 是 Verimag 研发维护的形式化方法模型检查工具。该工具的理…...

告别 “幻觉” 回答:RAG 中知识库与生成模型的 7 种对齐策略

一、引言 大语言模型&#xff08;LLM&#xff09;在文本生成领域展现出惊人能力&#xff0c;但 “幻觉” 问题&#xff08;生成虚构或偏离事实的内容&#xff09;始终是落地应用的核心挑战。检索增强生成&#xff08;RAG&#xff09;通过将外部知识库与 LLM 结合&#xff0c;形…...

【Web应用服务器_Tomcat】一、Tomcat基础与核心功能详解

在 Java Web 应用开发领域&#xff0c;Apache Tomcat 是一座不可或缺的基石。作为一款开源、轻量级的 Servlet 容器和 Web 服务器&#xff0c;Tomcat 以其稳定可靠、易于部署和高度可定制性&#xff0c;被广泛应用于各类 Web 应用的部署与运行。 一、Tomcat 简介​ Tomcat 是…...

Cesium实现地形可视域分析

Cesium实现可视化分析 一、地形可视域主要实现技术(Ray + 地形碰撞检测) Cesium 本身的 Ray 类可以用来执行非常精确的射线检测,我们可以结合地形高度(sample)来逐点检测光线是否与 terrain 相交,从而判断是否可见。 1.1 优势 实时判断每条射线是否被 terrain 遮挡地形…...

Java—— 常见API介绍 第五期

JDK8以后新增的时间相关类 Date类ZoneId&#xff1a;时区Instant&#xff1a;时间戳ZoneDateTime&#xff1a;带时区的时间 日期格式化类 SimpleDateFormat DateTimeFormatter&#xff1a;用于时间的格式化和解析 日历类 Calendar LocalDate&#xff1a;年、月、日LocalTime…...

ViewPager FragmentPagerAdapter在系统杀死应用后重建时UI不刷新的问题

解决方案 通过重写getItemId方法&#xff0c;返回Fragment的hashCode&#xff1a; Override public long getItemId(int position) {/*** 恢复状态重建时&#xff0c;新的 Fragment 不刷新UI。* 原因&#xff1a;instantiateItem 中通过 mFragmentManager.findFragmentByTag(…...