Spring AOP 入门教程:基础概念与实现
目录
第一章:AOP概念的引入
第二章:AOP相关的概念
1. AOP概述
2. AOP的优势
3. AOP的底层原理
第三章:Spring的AOP技术 - 配置文件方式
1. AOP相关的术语
2. AOP配置文件方式入门
3. 切入点的表达式
4. AOP的通知类型
第四章:Spring AOP技术 - 注解方式
1. 创建 Maven 工程,导入依赖
2. 编写接口并完成 IOC 配置
3. 编写切面类
4. 配置 XML 扫描注解
5. 配置 XML 自动代理
6. 编写 User 类
7. 通知类型注解
8. 测试类
9. 结果输出
Spring完整基础内容,请看这篇博客 :
Spring基础之——控制反转(IOC)、依赖注入(DI)与切面编程(AOP)概念详解(适合小白,初学者必看)_spring 控制反转、依赖注入、面向切面编程的代码呈现-CSDN博客文章浏览阅读1.1k次,点赞30次,收藏18次。本篇博客讲详细介绍Spring框架中的两个最核心且最基础的概念:控制反转(IOC)和面向切面编程(AOP)。以及如何通过IDEA来构建一个Spring项目,通过实战和理论结合的方式来让大家真的学会Spring这个最流行的Java框架。Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。它是为了解决企业应用开发的复杂性而创建的。_spring 控制反转、依赖注入、面向切面编程的代码呈现https://blog.csdn.net/Future_yzx/article/details/143406347?sharetype=blogdetail&sharerId=143406347&sharerefer=PC&sharesource=Future_yzx&spm=1011.2480.3001.8118
前言
在本篇博客中,我们将详细介绍 Spring AOP(面向切面编程) 的基本概念、应用及实现方法。AOP 是一种能够在不修改源代码的前提下对程序进行增强的技术,广泛应用于日志记录、性能统计、权限校验等领域。我们将从概念入手,逐步展示如何使用 Spring AOP 实现增强功能。
第一章:AOP概念的引入
首先我们来看一下用户登录的原理流程
我们先从一个简单的登录原理图开始思考,如果我们希望在登录功能中添加新的操作,例如权限校验,通常可以采取两种方式:
- 修改源代码:直接在原有代码中添加权限校验逻辑。
- 不修改源代码:通过 AOP 技术,在不改变现有代码的情况下进行增强。
Spring AOP 技术恰恰解决了第二种需求,它允许我们在现有业务逻辑上加入横向功能(如权限检查、日志记录等),而不需要直接修改源代码。
第二章:AOP相关的概念
1. AOP概述
AOP(Aspect-Oriented Programming)是“面向切面编程”的缩写,它是对传统 OOP(面向对象编程) 的补充,通过在程序执行过程中动态地插入额外的功能来增强代码的可复用性与模块化。
Spring AOP 通过 代理 机制实现切面功能,通常在运行时为目标对象创建代理对象,从而实现方法增强。
2. AOP的优势
AOP 的核心优势在于它能够 解耦 业务逻辑和横向功能(如日志、事务、缓存等),从而提高代码的可维护性、重用性及开发效率。
AOP 的优势总结:
- 减少重复代码:避免在每个业务方法中重复相同的代码。
- 提高开发效率:通过统一处理横向功能,简化业务逻辑。
- 方便维护:可以在不改变核心业务逻辑的前提下,修改或添加横向功能。
3. AOP的底层原理
Spring AOP 的实现基于 动态代理技术,主要有两种方式:
(1)JDK 动态代理:通过接口创建代理类。
- 为接口创建代理类的字节码文件
- 使用ClassLoader将字节码文件加载到JVM
- 创建代理类实例对象,执行对象的目标方法
(2)CGLIB 代理:通过继承目标类生成代理类,适用于没有接口的类。
- 为类生成代理对象,被代理类有没有接口都无所谓,底层是生成子类,继承被代理类
第三章:Spring的AOP技术 - 配置文件方式
1. AOP相关的术语
在 AOP 中,以下是一些关键术语:
- Joinpoint(连接点):表示在程序中可以插入增强的地方,通常是方法。
- Pointcut(切入点):定义了哪些连接点会被拦截。
- Advice(通知):在切入点处执行的代码,分为不同类型(前置通知、后置通知、环绕通知等)。
- Aspect(切面):切入点与通知的结合,表示一个完整的 AOP 增强。
2. AOP配置文件方式入门
首先,我们需要创建一个 Maven 项目并导入以下依赖:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version></dependency>
</dependencies>
创建被增强的类(目标类)
// 被增强的类
public class User {// 连接点/切入点public void add() {System.out.println("add......");}public void update() {System.out.println("update......");}
}
创建切面类
public class UserProxy {// 增强/通知 ---》前置通知public void before() {System.out.println("before.............");}
}
在配置文件中完成aop的配置
<!-- 定义目标类和切面类 -->
<bean id="user" class="com.aopImpl.User"></bean>
<bean id="userProxy" class="com.aopImpl.UserProxy"></bean><!-- 配置切面 -->
<aop:config><!-- 配置切面 = 切入点 + 通知组成 --><aop:aspect ref="userProxy"><!-- 前置通知:UserServiceImpl的save方法执行前,会增强 --><aop:before method="before" pointcut="execution(public void com.aopImpl.User.add())"/></aop:aspect>
</aop:config>
测试类
public class DemoTest {@Testpublic void aopTest1() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User) applicationContext.getBean("user");user.add();}
}
3. 切入点的表达式
再配置切入点的时候,需要定义表达式,具体展开如下:
① 切入点表达式的格式如下:
execution( [修饰符] [返回值类型] [类全路径] [方法名 ( [参数] )] )
注意:
- 修饰符不是必须要出现的,可以省略不写。
- 返回值类型是不能省略不写的,根据你的方法来编写返回值,可以使用 * 代替。
② 包名,类名,方法名,参数的规则如下:
例如:com.qcby.demo3.BookDaoImpl.save()
- 首先包名,类名,方法名不能省略不写,可以使用 * 代替
- 中间的包名可以使用 * 号代替
- 类名也可以使用 * 号代替,例如有类似的写法: *DaoImpl
- 方法也可以使用 * 号代替
- 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..
比较通用的表达式:execution(* com.qcby.*.ServiceImpl.save(..))
举例2:对 com.qcby.demo3.BookDaoImpl 当中所有的方法进行增强
execution(* com.qcby.*.ServiceImpl.*(..))
举例3:对 com.qcby.demo3 包当中所有的方法进行增强
execution(* com.qcby.*.*.*(..))
代码实例:
<!--配置切面-->
<aop:config><!--配置切面 = 切入点 + 通知组成--><aop:aspect ref="userProxy"><!--切入点的表达式execution() 固定的写法public 是可以省略不写的方法的返回值 int String 通用的写法,可以编写 * 不能省略不写的包名+类名 不能省略不写的,编写 * com.*方法名称 add() 可以写 *参数列表 (..) 表示任意类型和个数的参数比较通用的表达式:execution(* com.*.User.add(..))--><aop:before method="before" pointcut="execution(* com.*.User.add(..))"/></aop:aspect>
</aop:config>
4. AOP的通知类型
Spring AOP 提供了多种通知类型,以下是常用的通知:
- 前置通知(Before):在目标方法执行前进行增强。
- 环绕通知(Around):在目标方法执行前后都可以增强,且需要手动调用目标方法。
- 最终通知(After):无论目标方法执行成功还是失败,都会执行。
- 后置通知(AfterReturning):目标方法执行成功后执行。
- 异常通知(AfterThrowing):当目标方法抛出异常时执行。
接下来,我们一一展开并配置这些通知。
1. 前置通知(Before)
目标:目标方法执行前进行增强。
适用场景:例如,进行权限检查或日志记录时,在方法执行之前就进行操作。
代码示例:
// 前置通知
public void before() {System.out.println("before.............");
}
XML 配置:
<aop:before method="before" pointcut="execution(public void com.aopImpl.User.add())"/>
2. 环绕通知(Around)
目标:目标方法执行前后都可以进行增强。需要手动执行目标方法。
适用场景:例如,在方法执行前后做性能监控、事务管理等,或者在执行方法之前和之后加上额外的逻辑。
代码示例:
// 环绕通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("before.............");// 执行被增强的方法proceedingJoinPoint.proceed(); System.out.println("after.............");
}
XML 配置:
<aop:around method="around" pointcut="execution(* com.*.User.add(..))"/>
3. 最终通知(After)
目标:目标方法执行成功或者失败时都进行增强。
适用场景:例如,无论方法执行是否成功,都需要执行清理操作(如关闭资源)。
代码示例:
// 最终通知
public void after() {System.out.println("after.............");
}
XML 配置:
<aop:after method="after" pointcut="execution(* com.*.User.add(..))"/>
4. 后置通知(AfterReturning)
目标:目标方法执行成功后进行增强。
适用场景:例如,在方法执行成功后进行记录日志,或者根据方法的返回值进行后续处理。
代码示例:
// 后置通知
public void afterReturning() {System.out.println("afterReturning.............");
}
XML 配置:
<aop:after-returning method="afterReturning" pointcut="execution(public void com.aopImpl.User.add())"/>
5. 异常通知(AfterThrowing)
目标:目标方法执行失败(抛出异常)时进行增强。
适用场景:例如,当目标方法出现异常时记录日志、发送报警等。
代码示例:
// 异常通知
public void afterThrowing() {System.out.println("afterThrowing.............");
}
连接点/切入点:
这里的目标方法 add()
在执行时故意抛出异常,用于触发异常通知。
// 连接点/切入点
public void add() {int a = 10 / 0; // 故意抛出异常System.out.println("add......");
}
XML 配置:
<aop:after-throwing method="afterThrowing" pointcut="execution(public void com.aopImpl.User.add())"/>
适用场景:
- 前置通知:适用于方法执行前需要进行一些准备工作,如权限验证、输入检查等。
- 环绕通知:适用于你需要控制方法执行的前后逻辑,能够在方法执行前后插入自定义行为。
- 最终通知:适用于在方法执行后无论成功与否都需要执行的操作,如资源清理等。
- 后置通知:适用于方法执行成功后进行的操作,例如记录成功日志或结果处理。
- 异常通知:适用于方法执行时发生异常,需要对异常进行处理,如记录日志或发送告警通知。
第四章:Spring AOP技术 - 注解方式
下面用一个AOP注解方式入门程序来为大家演示:注解方式使用AOP。
1. 创建 Maven 工程,导入依赖
在 pom.xml
中添加必要的 Spring 相关依赖。具体依赖配置略。
2. 编写接口并完成 IOC 配置
(此部分略,假设已经完成)
3. 编写切面类
给切面类添加 @Aspect
注解,编写增强的方法,使用通知类型注解声明:
@Component
@Aspect // 生成代理对象
public class UserProxy {// 增强/通知 ---》前置通知@Before(value = "execution(* com.*.User.add(..))")public void before() {System.out.println("before.............");}// 环绕通知@Around(value = "execution(* com.*.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("before.............");// 执行被增强的方法proceedingJoinPoint.proceed();System.out.println("after.............");}// 最终通知@After(value = "execution(* com.*.User.add(..))")public void after() {System.out.println("after.............");}// 异常通知@AfterThrowing(value = "execution(* com.*.User.add(..))")public void afterThrowing() {System.out.println("afterThrowing.............");}// 后置通知@AfterReturning(value = "execution(* com.*.User.add(..))")public void afterReturning() {System.out.println("afterReturning.............");}
}
4. 配置 XML 扫描注解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 开启注解扫描 --><context:component-scan base-package="com.aopImpl"></context:component-scan></beans>
5. 配置 XML 自动代理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 开启注解扫描 --><context:component-scan base-package="com.aopImpl"></context:component-scan><!-- 开启 AspectJ 自动代理 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>
6. 编写 User
类
@Component
public class User {// 连接点/切入点public void add() {System.out.println("add......");}
}
7. 通知类型注解
@Before
: 前置通知@AfterReturning
: 后置通知@Around
: 环绕通知(目标对象方法默认不执行,需要手动调用)@After
: 最终通知@AfterThrowing
: 异常抛出通知
@Component
@Aspect //生成代理对象
public class UserProxy {//增强/通知 ---》前置通知@Before(value = "execution(* com.*.User.add(..))")public void before(){System.out.println("before.............");}// 环绕通知@Around(value = "execution(* com.*.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("before.............");// 执行被增强的方法proceedingJoinPoint.proceed();System.out.println("after.............");}// 最终通知@After(value = "execution(* com.*.User.add(..))")public void after() {System.out.println("after.............");}//异常通知@AfterThrowing(value = "execution(* com.*.User.add(..))")public void afterThrowing() {System.out.println("afterThrowing.............");}//后置通知@AfterReturning(value = "execution(* com.*.User.add(..))")public void afterReturning() {System.out.println("afterReturning.............");}
}
8. 测试类
@Test
public void aopTest1() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User) applicationContext.getBean("user");user.add();
}
9. 结果输出
当 user.add()
被调用时,输出将会是:
before.............
before.............
add......
after.............
after.............
afterReturning.............
这样就完成了一个基本的 AOP 注解方式入门程序,涵盖了前置通知、后置通知、环绕通知、最终通知和异常通知的使用。
如果有更多问题或者需要进一步的讲解,随时告诉我!
结语
在本文中,我们介绍了 Spring AOP 的基本概念、配置文件方式和注解方式的实现。通过 Spring AOP,我们可以在不修改源代码的前提下灵活地为现有代码添加横向功能,提高代码的复用性和可维护性。希望本文能帮助你更好地理解和使用 Spring AOP!
相关文章:

Spring AOP 入门教程:基础概念与实现
目录 第一章:AOP概念的引入 第二章:AOP相关的概念 1. AOP概述 2. AOP的优势 3. AOP的底层原理 第三章:Spring的AOP技术 - 配置文件方式 1. AOP相关的术语 2. AOP配置文件方式入门 3. 切入点的表达式 4. AOP的通知类型 第四章&#x…...

DeepSeek 核心技术全景解析
DeepSeek 核心技术全景解析:突破性创新背后的设计哲学 DeepSeek的创新不仅仅是对AI基础架构的改进,更是一场范式革命。本文将深入剖析其核心技术,探讨 如何突破 Transformer 计算瓶颈、如何在 MoE(Mixture of Experts)…...

90,【6】攻防世界 WEB Web_php_unserialize
进入靶场 进入靶场 <?php // 定义一个名为 Demo 的类 class Demo { // 定义一个私有属性 $file,默认值为 index.phpprivate $file index.php;// 构造函数,当创建类的实例时会自动调用// 接收一个参数 $file,用于初始化对象的 $file 属…...

实现网站内容快速被搜索引擎收录的方法
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/6.html 实现网站内容快速被搜索引擎收录,是网站运营和推广的重要目标之一。以下是一些有效的方法,可以帮助网站内容更快地被搜索引擎发现和收录: 一、确…...

WSL2中安装的ubuntu搭建tftp服务器uboot通过tftp下载
Windows中安装wsl2,wsl2里安装ubuntu。 1. Wsl启动后 1)Windows下ip ipconfig 以太网适配器 vEthernet (WSL (Hyper-V firewall)): 连接特定的 DNS 后缀 . . . . . . . : IPv4 地址 . . . . . . . . . . . . : 172.19.32.1 子网掩码 . . . . . . . .…...

机器学习优化算法:从梯度下降到Adam及其变种
机器学习优化算法:从梯度下降到Adam及其变种 引言 最近deepseek的爆火已然说明,在机器学习领域,优化算法是模型训练的核心驱动力。无论是简单的线性回归还是复杂的深度神经网络,优化算法的选择直接影响模型的收敛速度、泛化性能…...

[SAP ABAP] 静态断点的使用
在 ABAP 编程环境中,静态断点通过关键字BREAK-POINT实现,当程序执行到这一语句时,会触发调试器中断程序的运行,允许开发人员检查当前状态并逐步跟踪后续代码逻辑 通常情况下,在代码的关键位置插入静态断点可以帮助开发…...

129.求根节点到叶节点数字之和(遍历思想)
Problem: 129.求根节点到叶节点数字之和 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 直接利用二叉树的先序遍历,将遍历过程中的节点值先利用字符串拼接起来遇到根节点时再转为数字并累加起来,在归的过程中…...

NCCL、HCCL、通信、优化
文章目录 从硬件PCIE、NVLINK、RDMA原理到通信NCCL、MPI原理!通信实现方式:机器内通信、机器间通信通信实现方式:通讯协调通信实现方式:机器内通信:PCIe通信实现方式:机器内通信:NVLink通信实现…...

unity学习21:Application类与文件存储的位置
目录 1 unity是一个跨平台的引擎 1.1 使用 Application类,去读写文件 1.2 路径特点 1.2.1 相对位置/相对路径: 1.2.2 固定位置/绝对路径: 1.3 测试方法,仍然挂一个C#脚本在gb上 2 游戏数据文件夹路径(只读&…...

17 一个高并发的系统架构如何设计
高并发系统的理解 第一:我们设计高并发系统的前提是该系统要高可用,起码整体上的高可用。 第二:高并发系统需要面对很大的流量冲击,包括瞬时的流量和黑客攻击等 第三:高并发系统常见的需要考虑的问题,如内存不足的问题,服务抖动的…...

Spring Boot 实例解析:配置文件
SpringBoot 的热部署: Spring 为开发者提供了一个名为 spring-boot-devtools 的模块来使用 SpringBoot 应用支持热部署,提高开发者的效率,无需手动重启 SpringBoot 应用引入依赖: <dependency> <groupId>org.springfr…...

pytorch图神经网络处理图结构数据
人工智能例子汇总:AI常见的算法和例子-CSDN博客 图神经网络(Graph Neural Networks,GNNs)是一类能够处理图结构数据的深度学习模型。图结构数据由节点(vertices)和边(edges)组成&a…...

计算机网络一点事(23)
传输层 端口作用:标识主机特定进程,TCP,UDP协议 端口号分类:服务器:0-1023,熟知 1024-49151 登记 客户端:49152-65535 功能:实现端到端,进程到进程的通信,…...

(9)下:学习与验证 linux 里的 epoll 对象里的 EPOLLIN、 EPOLLHUP 与 EPOLLRDHUP 的不同。小例子的实验
(4)本实验代码的蓝本,是伊圣雨老师里的课本里的代码,略加改动而来的。 以下是 服务器端的代码: 每当收到客户端的报文时,就测试一下对应的 epoll 事件里的事件标志,不读取报文内容,…...

DeepSeek-R1模型1.5b、7b、8b、14b、32b、70b和671b有啥区别?
deepseek-r1的1.5b、7b、8b、14b、32b、70b和671b有啥区别?码笔记mabiji.com分享:1.5B、7B、8B、14B、32B、70B是蒸馏后的小模型,671B是基础大模型,它们的区别主要体现在参数规模、模型容量、性能表现、准确性、训练成本、推理成本…...

一、html笔记
(一)前端概述 1、定义 前端是Web应用程序的前台部分,运行在PC端、移动端等浏览器上,展现给用户浏览的网页。通过HTML、CSS、JavaScript等技术实现,是用户能够直接看到和操作的界面部分。上网就是下载html文档,浏览器是一个解释器,运行从服务器下载的html文件,解析html、…...

AI大模型开发原理篇-2:语言模型雏形之词袋模型
基本概念 词袋模型(Bag of Words,简称 BOW)是自然语言处理和信息检索等领域中一种简单而常用的文本表示方法,它将文本看作是一组单词的集合,并忽略文本中的语法、词序等信息,仅关注每个词的出现频率。 文本…...

基于微信小程序的实习记录系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

【LLM】DeepSeek-R1-Distill-Qwen-7B部署和open webui
note DeepSeek-R1-Distill-Qwen-7B 的测试效果很惊艳,CoT 过程可圈可点,25 年应该值得探索更多端侧的硬件机会。 文章目录 note一、下载 Ollama二、下载 Docker三、下载模型四、部署 open webui 一、下载 Ollama 访问 Ollama 的官方网站 https://ollam…...

【Elasticsearch】 Intervals Query
Elasticsearch Intervals Query 返回基于匹配术语的顺序和接近度的文档。 intervals 查询使用 匹配规则,这些规则由一小组定义构建而成。这些规则然后应用于指定 field 中的术语。 这些定义生成覆盖文本中术语的最小间隔序列。这些间隔可以进一步由父源组合和过滤…...

DeepSeek技术深度解析:从不同技术角度的全面探讨
DeepSeek技术深度解析:从不同技术角度的全面探讨 引言 DeepSeek是一个集成了多种先进技术的平台,旨在通过深度学习和其他前沿技术来解决复杂的问题。本文将从算法、架构、数据处理以及应用等不同技术角度对DeepSeek进行详细分析。 一、算法层面 深度学…...

Docker 部署 Starrocks 教程
Docker 部署 Starrocks 教程 StarRocks 是一款高性能的分布式分析型数据库,主要用于 OLAP(在线分析处理)场景。它最初是由百度的开源团队开发的,旨在为大数据分析提供一个高效、低延迟的解决方案。StarRocks 支持实时数据分析&am…...

【LLM-agent】(task6)构建教程编写智能体
note 构建教程编写智能体 文章目录 note一、功能需求二、相关代码(1)定义生成教程的目录 Action 类(2)定义生成教程内容的 Action 类(3)定义教程编写智能体(4)交互式操作调用教程编…...

29.Word:公司本财年的年度报告【13】
目录 NO1.2.3.4 NO5.6.7 NO8.9.10 NO1.2.3.4 另存为F12:考生文件夹:Word.docx选中绿色标记的标题文本→样式对话框→单击右键→点击样式对话框→单击右键→修改→所有脚本→颜色/字体/名称→边框:0.5磅、黑色、单线条:点…...

14 2D矩形模块( rect.rs)
一、 rect.rs源码 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENS…...

【Unity3D】实现2D角色/怪物死亡消散粒子效果
核心:这是一个Unity粒子系统自带的一种功能,可将粒子生成控制在一个Texture图片网格范围内,并且粒子颜色会自动采样图片的像素点颜色,之后则是粒子编辑出消散效果。 Particle System1物体(爆发式随机速度扩散10000个粒…...

Linux - 进程间通信(3)
目录 3、解决遗留BUG -- 边关闭信道边回收进程 1)解决方案 2)两种方法相比较 4、命名管道 1)理解命名管道 2)创建命名管道 a. 命令行指令 b. 系统调用方法 3)代码实现命名管道 构建类进行封装命名管道&#…...

3、C#基于.net framework的应用开发实战编程 - 实现(三、三) - 编程手把手系列文章...
三、 实现; 三.三、编写应用程序; 此文主要是实现应用的主要编码工作。 1、 分层; 此例子主要分为UI、Helper、DAL等层。UI负责便签的界面显示;Helper主要是链接UI和数据库操作的中间层;DAL为对数据库的操…...

C++编程语言:抽象机制:泛型编程(Bjarne Stroustrup)
泛型编程(Generic Programming) 目录 24.1 引言(Introduction) 24.2 算法和(通用性的)提升(Algorithms and Lifting) 24.3 概念(此指模板参数的插件)(Concepts) 24.3.1 发现插件集(Discovering a Concept) 24.3.2 概念与约束(Concepts and Constraints) 24.4 具体化…...