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…...
ElasticSearch view
基础知识类 elasticsearch和数据库之间区别? elasticsearch:面向文档,数据以文档的形式存储,即JSON格式的对象。更强调数据的搜索、索引和分析。 数据库:更侧重于事务处理、数据的严格结构化和完整性,适用于…...
一文读懂Python之random模块(31)
random模块是Python的内置标准库,用于生成各类随机数,可以用作生成网站初始登录密码和随机验证码。 一、random模块简介 random模块可以生成随机数,包括随机整数、浮点数、随机元素等。 二、random模块相关概念 随机数: 是指在…...
12.udp
12.udp **1. UDP特性****2. UDP编程框架(C/S模式)****3. UDP发送接收函数****4. UDP编程练习** 1. UDP特性 连接特性:无链接,通信前无需像TCP那样建立连接。可靠性:不可靠,不保证数据按序到达、不保证数据…...
Upscayl-官方开源免费图像AI增强软件
upscayl 链接:https://pan.xunlei.com/s/VOI0Szqe0fCwSSUSS8zRqKf7A1?pwdhefi#...
【Super Tilemap Editor使用详解】(十七):常见问题解答(FAQ)
1.问题:我更新了 Unity 版本后,资源无法正常工作或代码出现错误。 解答:当你使用不同版本的 Unity 打开项目时,应该删除项目根目录下的 Library 文件夹。此外,如果遇到窗口问题,可以将窗口布局重置为默认布局。 2.问题:我在 SceneView 中看不到工具栏,也无法在图块地图…...
SpringBoot Web开发(SpringMVC)
SpringBoot Web开发(SpringMVC) MVC 核心组件和调用流程 Spring MVC与许多其他Web框架一样,是围绕前端控制器模式设计的,其中中央 Servlet DispatcherServlet 做整体请求处理调度! . 除了DispatcherServletSpringMVC还会提供其他…...
苍穹外卖第一天
角色分工 技术选型 pojo子模块 nginx反向代理 MD5密码加密...
C# Winform enter键怎么去关联button
1.关联按钮上的Key事件按钮上的keypress,keydown,keyup事件随便一个即可private void textBox1_KeyDown(object sender, KeyEventArgs e){if (e.KeyCode Keys.Enter){this.textBox2.Focus();}}2.窗体上的事件private void textBox2_KeyPress(object sen…...
LeGO LOAM坐标系问题的自我思考
LeGO LOAM坐标系问题的自我思考 IMU坐标系LeGO LOAM代码分析代码 对于IMU输出测量值的integration积分过程欧拉角的旋转矩阵VeloToStartIMU()函数TransformToStartIMU(PointType *p) IMU坐标系 在LeGO LOAM中IMU坐标系的形式采用前(x)-左(y)-上(z)的形式,IMU坐标系…...
vim交换文件的作用
1.数据恢复:因为vim异常的退出,使用交换文件可以恢复之前的修改内容。 2.防止多人同时编辑:vim检测到交换文件的存在,会给出提示,以避免一个文件同时被多人编辑。 (vim交换文件的工作原理:vim交换文件的工作…...
PHP实现混合加密方式,提高加密的安全性(代码解密)
代码1: <?php // 需要加密的内容 $plaintext 授权服务器拒绝连接;// 1. AES加密部分 $aesKey openssl_random_pseudo_bytes(32); // 生成256位AES密钥 $iv openssl_random_pseudo_bytes(16); // 生成128位IV// AES加密(CBC模式)…...
五. Redis 配置内容(详细配置说明)
五. Redis 配置内容(详细配置说明) 文章目录 五. Redis 配置内容(详细配置说明)1. Units 单位配置2. INCLUDES (包含)配置3. NETWORK (网络)配置3.1 bind(配置访问内容)3.2 protected-mode (保护模式)3.3 port(端口)配置3.4 timeout(客户端超时时间)配置3.5 tcp-keepalive()配置…...
安卓通过网络获取位置的方法
一 方法介绍 1. 基本权限设置 首先需要在 AndroidManifest.xml 中添加必要权限: xml <uses-permission android:name"android.permission.INTERNET" /> <uses-permission android:name"android.permission.ACCESS_NETWORK_STATE" /&g…...
python leetcode 笔记
只为记录一些python相关的特殊写法 无穷大,无穷小,NAN float(inf), float(-inf), float(nan) 判断字符的类型 isdigit(x) isspace(x) 字符串拼接 /.join([a,b,c]) # a/b/c 格式转换,字符转整形 ord(a) # 97 chr(97) # a 进制转…...
使用HttpClient和HttpRequest发送HTTP请求
项目中经常会用到向第三方系统发送请求来传递数据或者获得信息,一般用的比较多的为HttpClient 和 HttpRequest,这里简要总结一下 HttpClient 和 HttpRequest 的用法 一、HttpClient 1. 发送get请求 public static String get(String url, Map<Stri…...
(9) 上:学习与验证 linux 里的 epoll 对象里的 EPOLLIN、 EPOLLHUP 与 EPOLLRDHUP 的不同
(1)经过之前的学习。俺认为结论是这样的,因为三次握手到四次挥手,到 RST 报文,都是 tcp 连接上收到了报文,这都属于读事件。所以: EPOLLIN : 包含了读事件, FIN 报文的正常四次挥手、…...
C#属性和字段(访问修饰符)
不同点逻辑性/灵活性存储性访问性使用范围安全性属性(Property)源于字段,对字段的扩展,逻辑字段并不占用实际的内存可以被其他类访问对接收的数据范围做限定,外部使用增加了数据的安全性字段(Field)不经过逻辑处理占用内存的空间及位置大部分字段不能直接被访问内存使用不安全 …...
【C语言指针】指针和函数
文章目录 一、前言二、指针函数2.1 概念2.2 定义2.3 具体例子 三、函数指针3.1 概念3.2 定义3.3 具体例子3.4 回调函数3.4.1 概念3.4.2 例子13.4.3 例子2 四、函数指针数组4.1 概念4.2 定义4.3 具体例子 五、函数指针数组的指针5.1 概念5.2 定义5.3 具体例子 一、前言 关于指针…...
因果推断与机器学习—用机器学习解决因果推断问题
Judea Pearl 将当前备受瞩目的机器学习研究戏谑地称为“仅限于曲线拟合”,然而,曲线拟合的实现绝非易事。机器学习模型在图像识别、语音识别、自然语言处理、蛋白质分子结构预测以及搜索推荐等多个领域均展现出显著的应用效果。 在因果推断任务中,在完成因果效应识别之后,需…...
2025全自动企业站群镜像管理系统 | 支持繁简转换拼音插入
2025全自动企业站群镜像管理系统 | 支持繁简转换拼音插入 在全球化的今天,企业面临着管理多站点的挑战,尤其是跨语言和地理位置的站点。为此,我们设计了一套基于PHP的全自动企业站群镜像管理系统,它不仅能够自动化站点的管理&…...
基于阿里云百炼大模型Sensevoice-1的语音识别与文本保存工具开发
基于阿里云百炼大模型Sensevoice-1的语音识别与文本保存工具开发 摘要 随着人工智能技术的不断发展,语音识别在会议记录、语音笔记等场景中得到了广泛应用。本文介绍了一个基于Python和阿里云百炼大模型的语音识别与文本保存工具的开发过程。该工具能够高效地识别东…...
日志2025.2.1
日志2025.2.1 1.做了敌人状态机 public class EnermyStateMachine { public EnermyState currentState { get; private set; } public void InitializeState(EnermyState startState) { currentState startState; currentState.Enter(); } public void Change…...
GIS与相关专业软件汇总
闲来无事突然想整理一下看看 GIS及相关领域 究竟有多少软件或者工具包等。 我询问了几个AI工具并汇总了一个软件汇总,不搜不知道,一搜吓一跳,搜索出来了大量的软件,大部分软件或者工具包都没有见过,不知大家还有没有要…...
webrtc编译需要常用环境变量以及相关名词解释
set vs2022_installD:\\vs2022 set GYP_MSVS_OVERRIDE_PATHD:\\vs2022 set GYP_GENERATORSmsvs-ninja,ninja set WINDOWSSDKDIRD:\\Windows Kits\10 set DEPOT_TOOLS_WIN_TOOLCHAIN0 set GYP_MSVS_VERSION2022 这些环境变量是为了编译 WebRTC 时让 GYP/Depot Tools 正确找到 V…...
飞书项目流程入门指导手册
飞书项目流程入门指导手册 参考资料准备工作新建空间国际化配置新建工作项字段管理新建字段对接标识授权角色 流程管理基础说明流程节点配置流程节点的布局配置页面上布局按钮布局配置 流程节点驳回流程图展示自动化字段修改 局限性 参考资料 飞书官方参考文档:飞书…...
Android学习制作app(ESP8266-01S连接-简单制作)
一、理论 部分理论见arduino学习-CSDN博客和Android Studio安装配置_android studio gradle 配置-CSDN博客 以下直接上代码和效果视频,esp01S的收发硬件代码目前没有分享,但是可以通过另一个手机网络调试助手进行模拟。也可以直接根据我的代码进行改动…...
docker直接运行arm下的docker
运行环境是树莓派A 处理器是 arm32v6 安装了docker,运行lamp 编译安装php的时候发现要按天来算,于是用电脑vm下的Ubuntu系统运行arm的docker 然后打包到a直接导入运行就可以了 第一种方法 sudo apt install qemu-user-static 导入直接运行就可以了…...
PYH与MAC的桥梁MII/MIIM
在学习车载互联网时,看到了一句话,Processor通过DMA直接存储访问与MAC之间进行数据的交互,MAC通过MII介质无关接口与PHY之间进行数据的交互。常见的以太网硬件结构是,将MAC集成进Processor芯片,将PHY留在Processor片外…...
如何使用SliverList组件
文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了沉浸式状态栏相关的内容,本章回中将介绍SliverList组件.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里介绍的SliverList组件是一种列表类组件,类似我们之前介…...
