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…...
力扣面试150 快乐数 循环链表找环 链表抽象 哈希
Problem: 202. 快乐数 👩🏫 参考题解 Code public class Solution {public int squareSum(int n) {int sum 0;while(n > 0){int digit n % 10;sum digit * digit;n / 10;}return sum;}public boolean isHappy(int n) {int slow n, fast squa…...
【实战篇章】深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据
文章目录 深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据一、服务器如何响应前端请求HTTP 请求生命周期全解析1.前端发起 HTTP 请求(关键细节强化版)2. 服务器接收请求(深度优化版) 二、后端如何查看前…...
《AI大模型开发笔记》DeepSeek技术创新点
一、DeepSeek横空出世 DeepSeek V3 以颠覆性技术架构创新强势破局!革命性的上下文处理机制实现长文本推理成本断崖式下降,综合算力需求锐减90%,开启高效 AI 新纪元! 最新开源的 DeepSeek V3模型不仅以顶尖基准测试成绩比肩业界 …...
【大模型LLM面试合集】大语言模型架构_MHA_MQA_GQA
MHA_MQA_GQA 1.总结 在 MHA(Multi Head Attention) 中,每个头有自己单独的 key-value 对;标准的多头注意力机制,h个Query、Key 和 Value 矩阵。在 MQA(Multi Query Attention) 中只会有一组 k…...
实战技巧:如何快速增加网站的收录页面?
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/43.html 要快速增加网站的收录页面,可以从以下几个方面进行实战优化: 一、内容优化 高质量原创内容 确保网站内容具备高质量与原创性,满足搜索引擎对独…...
20-30 五子棋游戏
20-分析五子棋的实现思路_哔哩哔哩_bilibili20-分析五子棋的实现思路是一次性学会 Canvas 动画绘图(核心精讲50个案例)2023最新教程的第21集视频,该合集共计53集,视频收藏或关注UP主,及时了解更多相关视频内容。https:…...
PYH与MAC的桥梁MII/MIIM
在学习车载互联网时,看到了一句话,Processor通过DMA直接存储访问与MAC之间进行数据的交互,MAC通过MII介质无关接口与PHY之间进行数据的交互。常见的以太网硬件结构是,将MAC集成进Processor芯片,将PHY留在Processor片外…...
pytorch基于 Transformer 预训练模型的方法实现词嵌入(tiansz/bert-base-chinese)
以下是一个完整的词嵌入(Word Embedding)示例代码,使用 modelscope 下载 tiansz/bert-base-chinese 模型,并通过 transformers 加载模型,获取中文句子的词嵌入。 from modelscope.hub.snapshot_download import snaps…...
探秘 TCP TLP:从背景到实现
回家的路上还讨论了个关于 TCP TLP 的问题,闲着无事缕一缕。本文内容参考自 Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses 以及 Linux 内核源码。 TLP,先说缘由。自 TCP 引入 Fast retrans 机制就是为了尽力避免 RTO…...
MCU内部ADC模块误差如何校准
本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时,也能帮助其他需要参考的朋友。如有谬误,欢迎大家进行指正。 一、ADC误差校准引言 MCU 片内 ADC 模块的误差总包括了 5 个静态参数 (静态失调,增益误差,微分非线性…...
国产之光DeepSeek架构理解与应用分析
目录 初步探索DeepSeek的设计 一、核心架构设计 二、核心原理与优化 三、关键创新点 四、典型应用场景 五、与同类模型的对比优势 六、未来演进方向 从投入行业生产的角度看 一、DeepSeek的核心功能扩展 二、机械电子工程产业中的具体案例 1. 预测性维护(Predictive…...
群晖NAS安卓Calibre 个人图书馆
docker 下载镜像johngong/calibre-web,安装之 我是本地的/docker/xxx/metadata目录 映射到 /usr/local/calibre-web/app/cps/metadata_provider CALIBREDB_OTHER_OPTION 删除 CALIBRE_SERVER_USER calibre_server_user 缺省用户名口令 admin admin123 另外有个N…...
openRv1126 AI算法部署实战之——Tensorflow模型部署实战
在RV1126开发板上部署Tensorflow算法,实时目标检测RTSP传输。视频演示地址 rv1126 yolov5 实时目标检测 rtsp传输_哔哩哔哩_bilibili 一、准备工作 从官网下载tensorflow模型和数据集 手动在线下载: https://github.com/tensorflow/models/b…...
HTML特殊符号的使用示例
目录 一、基本特殊符号的使用 1、空格符号: 2、小于号 和 大于号: 3、引号: 二、版权、注册商标符号的使用 1、版权符号:© 2、注册商标符号: 三、数学符号的使用 四、箭头符号的使用 五、货币符号的使用…...
如何对系统调用进行扩展?
扩展系统调用是操作系统开发中的一个重要任务。系统调用是用户程序与操作系统内核之间的接口,允许用户程序执行内核级操作(如文件操作、进程管理、内存管理等)。扩展系统调用通常包括以下几个步骤: 一、定义新系统调用 扩展系统调用首先需要定义新的系统调用的功能。系统…...
【MFC】C++所有控件随窗口大小全自动等比例缩放源码(控件内字体、列宽等未调整) 20250124
MFC界面全自动等比例缩放 1.在初始化里 枚举每个控件记录所有控件rect 2.在OnSize里,根据当前窗口和之前保存的窗口的宽高求比例x、y 3.枚举每个控件,根据比例x、y调整控件上下左右,并移动到新rect struct ControlInfo {CWnd* pControl;CRect original…...
前端 | 深入理解Promise
1. 引言 JavaScript 是一种单线程语言,这意味着它一次仅能执行一个任务。为了处理异步操作,JavaScript 提供了回调函数,但是随着项目处理并发任务的增加,回调地狱 (Callback Hell) 使异步代码很难维护。为此,ES6带来了…...
【视频+图文讲解】HTML基础2-html骨架与基本语法
图文教程 基本骨架 举个例子,下图所展示的为html的源代码 -!DOCTYPE:表示文档类型(后边写的html表示文档类型是html);其中“!”表示声明 只要是加这个声明标签的,浏览器就会把下边的源代码当…...
LabVIEW在电机自动化生产线中的实时数据采集与生产过程监控
在电机自动化生产线中,实时数据采集与生产过程监控是确保生产效率和产品质量的重要环节。LabVIEW作为一种强大的图形化编程平台,可以有效实现数据采集、实时监控和自动化控制。详细探讨如何利用LabVIEW实现这一目标,包括硬件选择、软件架构设…...
《深入理解HTTP交互与数据监控:完整流程与优化实践》
文章目录 🌐 全链路解析:HTTP请求响应与数据可视化监控一、HTTP请求响应全流程解析1. 全链路交互流程图2.关键技术实现2.1 前端请求构造(ES6语法示例)2.2 服务端处理架构(Node.js/Express) 二、数据可视化监…...
pytorch使用SVM实现文本分类
人工智能例子汇总:AI常见的算法和例子-CSDN博客 完整代码: import torch import torch.nn as nn import torch.optim as optim import jieba import numpy as np from sklearn.model_selection import train_test_split from sklearn.feature_extract…...
Recommender Systems with Large Models
一、引言 信息爆炸时代,用户面临信息过载,传统推荐系统依赖经典算法,难以满足需求。大模型基于深度学习,经大规模预训练,具备强大能力,能实现更精准推荐,为推荐系统发展开辟新路径。 二、大模…...
团体程序设计天梯赛-练习集——L1-028 判断素数
前言 一道10分的题目,相对来说比较简单,思考的时候要仔细且活跃,有时候在写代码的时候一些代码的出现很多余,并且会影响最后的结果 L1-028 判断素数 本题的目标很简单,就是判断一个给定的正整数是否素数。 输入格式…...
SCRM开发为企业提供全面客户管理解决方案与创新实践分享
内容概要 在当今的商业环境中,客户关系管理(CRM)变得越来越重要。而SCRM(社交客户关系管理)作为一种新兴的解决方案,正在帮助企业彻底改变与客户的互动方式。快鲸SCRM是一个引人注目的工具,它通…...
Axure PR 9 旋转效果 设计交互
大家好,我是大明同学。 这期内容,我们将学习Axure中的旋转效果设计与交互技巧。 旋转 创建旋转效果所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个按钮元件。 创建交互 创建按钮交互状态 1.选中按钮元件…...
自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数
代码: import torch import numpy as np import torch.nn as nn from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score# 定义数据:x_data 是特征,y_data 是标签(目标值) data [[-0…...
Linux02——Linux的基本命令
目录 ls 常用选项及功能 综合示例 注意事项 cd和pwd命令 cd命令 pwd命令 相对路径、绝对路径和特殊路径符 特殊路径符号 mkdir命令 1. 功能与基本用法 2. 示例 3. 语法与参数 4. -p选项 touch-cat-more命令 1. touch命令 2. cat命令 3. more命令 cp-mv-rm命…...
MySQL数据库(二)- SQL
目录 编辑 一 DDL (一 数据库操作 1 查询-数据库(所有/当前) 2 创建-数据库 3 删除-数据库 4 使用-数据库 (二 表操作 1 创建-表结构 2 查询-所有表结构名称 3 查询-表结构内容 4 查询-建表语句 5 添加-字段名数据类型 6 修改-字段数据类…...
Docker自定义镜像
Dockerfile自定义镜像 一:镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 我们以MySQL为例,来看看镜像的组成结构: 简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、…...
网络协议基础
文章目录 前言一、网络协议分层1.应用层2.传输层3.网络层4.数据链路层5.物理层 二、图解IP1.IP基本认识(1)IP的作用(2)IP与MAC的关系 2.IP地址的基础知识(1)IP地址的定义(2)IP地址的…...
c语言进阶(简单的函数 数组 指针 预处理 文件 结构体)
c语言补充 格式 void函数头 {} 中的是函数体 sum函数名 () 参数表 #include <stdio.h>void sum(int begin, int end) {int i;int sum 0;for (i begin ; i < end ; i) {sum i;}printf("%d到%d的和是%d\n", begin, end, sum); …...
Pytorch框架从入门到精通
目录 一、Tensors 1.1 初始化一个Tensor 1)赋值初始化 2)从 NumPy 数组初始化 3)从另一个张量 4)使用随机值或常量值 1.2 Tensor 的属性 1.3 对 Tensor 的操作 1.3.1 总体介绍 1.3.2 索引和切片 1.3.3 算术运算 矩阵乘…...
Vue.js组件开发-实现全屏图片文字缩放切换特效
使用 Vue 实现全屏图片文字缩放切换特效 步骤 创建 Vue 项目:使用 Vue CLI 来快速创建一个新的 Vue 项目。设计组件结构:创建一个包含图片和文字的组件,并实现缩放和切换效果。实现样式:使用 CSS 来实现全屏显示、缩放和切换动画…...
在 WSL2 中重启 Ubuntu 实例
在 WSL2 中重启 Ubuntu 实例,可以按照以下步骤操作: 方法 1: 使用 wsl 命令 关闭 Ubuntu 实例: 打开 PowerShell 或命令提示符,运行以下命令: wsl --shutdown这会关闭所有 WSL2 实例。 重新启动 Ubuntu: 再次打开 Ubuntu&#x…...
Flutter 新春第一弹,Dart 宏功能推进暂停,后续专注定制数据处理支持
在去年春节,Flutter 官方发布了宏(Macros)编程的原型支持, 同年的 5 月份在 Google I/O 发布的 Dart 3.4 宣布了宏的实验性支持,但是对于 Dart 内部来说,从启动宏编程实验开始已经过去了几年,但…...
Signature
打开得到加密脚本: import ecdsa import randomdef ecdsa_test(dA,k):sk ecdsa.SigningKey.from_secret_exponent(secexpdA,curveecdsa.SECP256k1)sig1 sk.sign(databHi., kk).hex()sig2 sk.sign(databhello., kk).hex()r1 int(sig1[:64], 16)s1 int(sig1[64:…...
UE求职Demo开发日志#18 数据表获取物品信息,添加背包模块
1 把获取物品信息改为读取数据表 先创建结构,暂时有这几个属性: USTRUCT(BlueprintType) struct ARPG_CPLUS_API FMyItemData:public FTableRowBase {GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite)int ItemId;//物品Id&#x…...
neo4j-community-5.26.0 create new database
1.edit neo4j.conf 把 # The name of the default database initial.dbms.default_databasehonglouneo4j # 写上自己的数据库名称 和 # Name of the service #5.0 server.windows_service_nameneo4j #4.0 dbms.default_databaseneo4j #dbms.default_databaseneo4jwind serve…...
项目中用的网关Gateway及SpringCloud
在现代微服务架构中,网关(Gateway)起到了至关重要的作用。它不仅负责路由请求,还提供了统一的认证、授权、负载均衡、限流等功能。Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个重要组件,专门为微服务架构提…...
《Ollama Python 库》
Ollama Python 库 Ollama Python 库提供了将 Python 3.8 项目与 Ollama 集成的最简单方法。 先决条件 应该安装并运行 Ollama拉取一个模型以与库一起使用:例如ollama pull <model>ollama pull llama3.2 有关可用模型的更多信息,请参阅 Ollama.com。…...
大模型概述(方便不懂技术的人入门)
1 大模型的价值 LLM模型对人类的作用,就是一个百科全书级的助手。有多么地百科全书,则用参数的量来描述, 一般地,大模型的参数越多,则该模型越好。例如,GPT-3有1750亿个参数,GPT-4可能有超过1万…...
Ubuntu16.04编译安装Cartographer 1.0版本
说明 官方文档 由于Ubuntu16.04已经是很老的系统,如果直接按照Cartographer官方安装文档安装会出现代码编译失败的问题,本文给出了解决这些问题的办法。正常情况下执行本文给出的安装方法即可成功安装。 依赖安装 # 这里和官方一致 # Install the req…...
AI-ISP论文Learning to See in the Dark解读
论文地址:Learning to See in the Dark 图1. 利用卷积网络进行极微光成像。黑暗的室内环境。相机处的照度小于0.1勒克斯。索尼α7S II传感器曝光时间为1/30秒。(a) 相机在ISO 8000下拍摄的图像。(b) 相机在ISO 409600下拍摄的图像。该图像存在噪点和色彩偏差。©…...
2 MapReduce
2 MapReduce 1. MapReduce 介绍1.1 MapReduce 设计构思 2. MapReduce 编程规范3. Mapper以及Reducer抽象类介绍1.Mapper抽象类的基本介绍2.Reducer抽象类基本介绍 4. WordCount示例编写5. MapReduce程序运行模式6. MapReduce的运行机制详解6.1 MapTask 工作机制6.2 ReduceTask …...
OpenCV:SIFT关键点检测与描述子计算
目录 1. 什么是 SIFT? 2. SIFT 的核心步骤 2.1 尺度空间构建 2.2 关键点检测与精细化 2.3 方向分配 2.4 计算特征描述子 3. OpenCV SIFT API 介绍 3.1 cv2.SIFT_create() 3.2 sift.detect() 3.3 sift.compute() 3.4 sift.detectAndCompute() 4. SIFT 关…...
初识Cargo:Rust的强大构建工具与包管理器
初识Cargo:Rust的强大构建工具与包管理器 如果你刚刚开始学习Rust,一定会遇到一个名字:Cargo。Cargo是Rust的官方构建工具和包管理器,它让Rust项目的创建、编译、测试和依赖管理变得非常简单。本文将带你快速了解Cargo的基本用法…...
LightM-UNet(2024 CVPR)
论文标题LightM-UNet: Mamba Assists in Lightweight UNet for Medical Image Segmentation论文作者Weibin Liao, Yinghao Zhu, Xinyuan Wang, Chengwei Pan, Yasha Wang and Liantao Ma发表日期2024年01月01日GB引用> Weibin Liao, Yinghao Zhu, Xinyuan Wang, et al. Ligh…...
2025年02月01日Github流行趋势
项目名称:oumi 项目地址url:https://github.com/oumi-ai/oumi 项目语言:Python 历史star数:544 今日star数:103 项目维护者:xrdaukar, oelachqar, taenin, wizeng23, kaisopos 项目简介:一切你需…...
自动化测试框架搭建-封装requests-优化
目的 1、实际的使用场景,无法避免的需要区分GET、POST、PUT、PATCH、DELETE等不同的方式请求,以及不同请求的传参方式 2、python中requests中,session.request方法,GET请求,只支持params传递参数 session.request(me…...