Spring面向切面编程

目录

1.AOP概述及Spring AOP实现原理

AOP概述 

AOP的应用场景 

 AOP的作用

Spring AOP概述

 Spring AOP的实现原理

 Spring AOP中Advice的分类

 2. 通过xml配置实现AOP

实现步骤:

 新增模块:

导入相关依赖:

新增实体类User 

 新增业务类UserService

定义切面类LogAspect 

 添加Spring核心配置文件

AOP配置说明 

注册切面类

配置切面

Spring配置文件中完成切面配置

编写测试类,验证效果

运行结果:

当前的目录结构:

​编辑 

3. 通过注解实现AOP

Spring AOP注解

 通过以下注解来定义通知 

用例设计(采用注解):

 实现步骤:

新增模块:

导入相关依赖: 

新增实体类User 

新增业务类UserService 

定义切面类LogAspect 

如何获取连接点信息 

@AfterReturning 

@Around

Spring配置文件中配置AspectJ自动代理 

编写测试类 

 运行结果:

当前的目录结构如下: 


1.AOP概述及Spring AOP实现原理

AOP概述 

AOP (Aspect Oriented Programming) 面向 切面编程
AOP 是一种编程的 思想
AOP 是对 OOP ( Object Oriented Programming ,面向对象 编程 ) 补充和 完善
利用 " 横切 " 技术 ,剖解开封装的对象内部,并将那些 与业务无关 ,但却 影响多 个类的 公共行为 封装到一个 可重用模块 ,并将其命名 Aspect 切面
作用 AOP 可以减少系统的重复代码,降低模块之间的耦合度,并有利于提升项目的可操作性和 可维护性

AOP的应用场景 

日志记录 :定义切面在方法执行前、执行后或异常抛出时记录日志
事务处理 :定义切面在方法开始前开启事务,在方法执行完毕后提交事务,在方法出现异常时回滚事务。
安全控制 :定义切面在方法执行前进行权限判断,如果用户没有权限,则抛出异常或转向到错误页面,以防止未经授权的访问。
缓存控制 :定义切面在方法执行前查询缓存中是否有数据,如果有则返回,否则执行方法并将方法返回值存入缓存中。
异常处理 :定义切面在方法执行过程中,如果出现异常,则进行 异常处理

 AOP的作用

不改变原有代码前提下,增加新功能

横切关注点:跨越应用程序多个模块。与业务逻辑无关处设置需关注部分,就是横切关注点。如日志,安全,缓存,事务等等

切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。

通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。

目标(Target):被通知对象。

代理(Proxy):向目标对象应用通知之后创建的对象。

切入点(PointCut):切面通知 执行的 “地点”的定义。

连接点(JointPoint):与切入点匹配的执行点。

Spring AOP概述

Spring AOPSpring框架中的一个模块,是基于AOP思想通过整合AspectJ框架实现的面向切面编程技术

AspectJ是一个面向切面编程的具体实现框架,定义了AOP的语法

 Spring AOP的实现原理

Spring AOP是基于动态代理技术实现的

在程序运行过程中,SpringAOP内部会基于JDK动态代理技术和cglib动态代理技术为目标对象生成代理对象

程序调用目标对象方法时,不是直接调用目标对象方法,而是先调用代理对象的方法,再调用目标对象的方法,从而对目标方法进行增强

 

 Spring AOP中Advice的分类

Spring AOP 通过 Advice 定义横切逻辑
支持 5 种类型的 Advice:

 

 2. 通过xml配置实现AOP

基于 Spring AOP 技术 在项目中配置 切面 实现 日志记录 的功能。
日志记录功能的具体要求如下:

1)当应用程序调用业务逻辑层组件方法之前,在控制台中打印出“开始调用方法

2)当应用程序调用业务逻辑层组件方法之后,在控制台中打印出“结束调用方法

3)当应用程序调用业务逻辑层组件方法出现了异常,在控制台中打印出“调用方法出现异常

实现步骤:

新建项目模块
整合 Spring AOP 框架 依赖
定义 切面类以及通知 方法
Spring 配置文件中完成 切面配置
运行测试类完成 切面测试

 新增模块:

打开上节的项目 spring6
新增模块 spring- aop -xml

 

导入相关依赖:

修改模块 spring- aop -xml pom.xml ,导入依赖
引入 spring-context 依赖 后,根据依赖的传递性,会自动引入 spring- aop 依赖
引入 Spring AspectJ 框架的整合依赖 spring-aspects ,因为我们要使用 AspectJ 框架的语法来进行配置切面

 xml配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.flowerfog</groupId><artifactId>Spring6</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>spring-aop-xml</artifactId><packaging>war</packaging><name>spring-aop-xml Maven Webapp</name><url>http://maven.apache.org</url><dependencies><!--spring context依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.2</version></dependency><!--spring和AspectJ整合依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.2</version></dependency><!--junit5测试--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.3.1</version></dependency><!--lombok插件--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies><build><finalName>spring-aop-xml</finalName></build>
</project>

新增实体类User 

package org.flowerfog.pojo;import lombok.Data;@Data
public class User {private Integer id;private String name;private String account;private String password;private Integer status;
}

 新增业务类UserService

package org.flowerfog.Service;import org.flowerfog.pojo.User;public class UserService {public void add(User user) {System.out.println("新增用户" + user);}public void removeById(Integer id) {System.out.println("删除Id=" + id + "的用户");}
}

定义切面类LogAspect 

package org.flowerfog.comm;public class LogAspect {// 前置通知public void before(){System.out.println("开始调用方法");}// 后置通知public void after(){System.out.println("结束调用方法");}// 异常通知public void exception(Exception ex){System.out.println("调用方法出席异常"+ex.getMessage());}
}

 添加Spring核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>

AOP配置说明 

注册切面类

配置切面

标签元素

作用

<aop:config>

AOP配置顶层节点,一个配置文件中可以包含多个<aop:config>节点

<aop:aspect>

配置切面该元素会将Spring容器中的Bean转换成切面Bean

<aop:pointcut>

配置切点,通过id属性指定切点唯一标识,通过expression属性指定切点表达式

 

 

Spring配置文件中完成切面配置

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册Bean--><bean id="userService" class="org.flowerfog.Service.UserService" /><bean id="logAspect" class="org.flowerfog.comm.LogAspect" /><!--AOP配置,需导入aop约束--><aop:config><!--配置切点--><aop:pointcut id="pointcut" expression="execution(* org.flowerfog.Service.*.*(..))"/><!--配置切面Bean--><aop:aspect ref="logAspect"><aop:before method="before" pointcut-ref="pointcut" /><aop:after method="after" pointcut-ref="pointcut" /><aop:after-throwing method="exception" pointcut-ref="pointcut" throwing="ex" /></aop:aspect></aop:config>
</beans>

编写测试类,验证效果


import org.flowerfog.Service.UserService;
import org.flowerfog.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class UserServiceTest {@Testpublic void add() {// 加载Spring核心配置文件ApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");// 获取bean对象UserService userService = (UserService) ctx.getBean("userService");User user = new User();user.setName("张三");user.setAccount("111");user.setPassword("123456");user.setStatus(0);userService.add(user);}
}

运行结果:

当前的目录结构:

 

3. 通过注解实现AOP

Spring 基于注解配置 AOP 需要 启用 AspectJ 自动代理 功能
启用 该功能后, Spring 框架会自动扫描应用程序中所有被 AOP 注解标记的类 , 并自动创建 AOP 代理 对象
Spring 配置文件中添加如下配置:

Spring AOP注解

@Aspect定义切面

切面类需注册到Spring容器@Aspect注解才能生效

@Pointcut定义切点

切面类中定义一个空方法并使用@Pointcut注解来定义切点

然后在@Pointcut注解中定义切点表达式用来匹配切入的目标类和方法

空方法的方法名就是切点的唯一标识id

 通过以下注解来定义通知 

 

用例设计(采用注解):

基于 Spring AOP 技术 在项目中配置 切面 实现 日志记录 的功能。
日志记录功能的具体要求如下:

1)当应用程序调用业务逻辑层组件方法之前,在控制台中打印出“开始调用方法

2)当应用程序调用业务逻辑层组件方法之后,在控制台中打印出“结束调用方法

3)当应用程序调用业务逻辑层组件方法出现了异常,在控制台中打印出“调用方法出现异常

 

 实现步骤:

新建项目模块

整合Spring AOP框架依赖

定义切面类以及通知方法

添加注解完成切面配置

运行测试类完成切面测试

新增模块:

新增模块 spring- aop -annotation

导入相关依赖: 

修改模块的 pom.xml ,导入依赖
引入 spring-context 依赖 后,根据依赖的传递性,会自动引入 spring- aop 依赖
引入 Spring AspectJ 框架的整合依赖 spring-aspects ,因为我们要使用 AspectJ 框架的语法来进行配置切面

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.flowerfog</groupId><artifactId>Spring6</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>spring-aop-annotation</artifactId><packaging>war</packaging><name>spring-aop-annotation Maven Webapp</name><url>https://maven.apache.org</url><dependencies><!--spring context依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.2</version></dependency><!--spring和AspectJ整合依赖--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.2</version></dependency><!--junit5测试--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.3.1</version></dependency><!--lombok插件--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies><build><finalName>spring-aop-annotation</finalName></build>
</project>

新增实体类User 

package org.flowerfog.pojo;import lombok.Data;@Data
public class User {private Integer id;private String name;private String account;private String password;private Integer status;
}

新增业务类UserService 

package org.flowerfog.Service;import org.flowerfog.pojo.User;public class UserService {public void add(User user) {System.out.println("新增用户" + user);}public void removeById(Integer id) {System.out.println("删除Id=" + id + "的用户");}
}

定义切面类LogAspect 

package org.flowerfog.comm;import org.aspectj.lang.annotation.*;// 定义切面
@Aspect
public class LogAspect {// 定义切点,其id为pointcut@Pointcut("execution(* org.flowerfog.Service.*.*(..))")public void pointcut(){}// 前置通知@Before("pointcut()")public void before(){System.out.println("开始调用方法");}// 后置通知@After("pointcut()")public void after(){System.out.println("结束调用方法");}// 异常通知@AfterThrowing(value = "pointcut()",throwing = "ex")public void exception(Exception ex){System.out.println("调用方法出现异常"+ex.getMessage());}
}

如何获取连接点信息 

通过切面对象方法的形参能获取连接点信息
数据类型为 JoinPoint

 

环绕通知可使用增强类型 ProceedingJoinPoint ,其 proceed() 执行连接点拦截到的方法

@AfterReturning 

在切面类中添加返回通知的代码

 LogAspect当前代码如下:

package org.flowerfog.comm;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.reflect.SourceLocation;
import org.springframework.util.ObjectUtils;import java.lang.reflect.Method;// 定义切面
@Aspect
public class LogAspect {// 定义切点,其id为pointcut@Pointcut("execution(* org.flowerfog.Service.*.*(..))")public void pointcut(){}// 前置通知@Before("pointcut()")public void before(){System.out.println("开始调用方法");}// 后置通知@After("pointcut()")public void after(){System.out.println("结束调用方法");}// 异常通知@AfterThrowing(value = "pointcut()",throwing = "ex")public void exception(Exception ex){System.out.println("调用方法出现异常"+ex.getMessage());}// 返回通知@AfterReturning("pointcut()")public void afterReturn(JoinPoint joinPoint){MethodSignature signature=(MethodSignature)joinPoint.getSignature(); // 获得目标对象的签名,及当前拦截到的方法Method method=signature.getMethod();String longString = joinPoint.toLongString();// 获得连接点的扩展全命名Object[] args = joinPoint.getArgs();// 返回连接点的参数数组Object target = joinPoint.getTarget();// 获得目标对象Object aThis = joinPoint.getThis();// 获得正在执行的目标对象JoinPoint.StaticPart staticPart = joinPoint.getStaticPart();// 获得连接点的静态部分SourceLocation sourceLocation = joinPoint.getSourceLocation();// 获得连接点对应的方法源地址String shortString = joinPoint.toShortString();// 获得连接点的缩写命名String kind = joinPoint.getKind();// 返回连接点的类型System.out.println("method:"+method+"\r\nlongString:"+longString);if (!ObjectUtils.isEmpty(args)) {for (Object arg : args) {System.out.println(arg);}}System.out.println("调用方法ok");}}

@Around

在切面类中添加环绕通知的代码

 最终LogAspect代码如下:

package org.flowerfog.comm;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.reflect.SourceLocation;
import org.springframework.util.ObjectUtils;import java.lang.reflect.Method;// 定义切面
@Aspect
public class LogAspect {// 定义切点,其id为pointcut@Pointcut("execution(* org.flowerfog.Service.*.*(..))")public void pointcut(){}// 前置通知@Before("pointcut()")public void before(){System.out.println("开始调用方法");}// 后置通知@After("pointcut()")public void after(){System.out.println("结束调用方法");}// 异常通知@AfterThrowing(value = "pointcut()",throwing = "ex")public void exception(Exception ex){System.out.println("调用方法出现异常"+ex.getMessage());}// 返回通知@AfterReturning("pointcut()")public void afterReturn(JoinPoint joinPoint){MethodSignature signature=(MethodSignature)joinPoint.getSignature(); // 获得目标对象的签名,及当前拦截到的方法Method method=signature.getMethod();String longString = joinPoint.toLongString();// 获得连接点的扩展全命名Object[] args = joinPoint.getArgs();// 返回连接点的参数数组Object target = joinPoint.getTarget();// 获得目标对象Object aThis = joinPoint.getThis();// 获得正在执行的目标对象JoinPoint.StaticPart staticPart = joinPoint.getStaticPart();// 获得连接点的静态部分SourceLocation sourceLocation = joinPoint.getSourceLocation();// 获得连接点对应的方法源地址String shortString = joinPoint.toShortString();// 获得连接点的缩写命名String kind = joinPoint.getKind();// 返回连接点的类型System.out.println("method:"+method+"\r\nlongString:"+longString);if (!ObjectUtils.isEmpty(args)) {for (Object arg : args) {System.out.println(arg);}}System.out.println("调用方法ok");}@Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//开始时间long beginTime = System.currentTimeMillis();//执行目标方法Object result = joinPoint.proceed();//执行时长(毫秒)long time = System.currentTimeMillis()-beginTime;System.out.println("执行时长(毫秒):"+time);return  result;}}

Spring配置文件中配置AspectJ自动代理 

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册Bean--><bean id="userService" class="org.flowerfog.Service.UserService" /><bean id="logAspect" class="org.flowerfog.comm.LogAspect" /><!--启用AspectJ自动代理--><aop:aspectj-autoproxy />
</beans>

编写测试类 


import org.flowerfog.Service.UserService;
import org.flowerfog.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class UserServiceTest {@Testpublic void add() {// 加载Spring核心配置文件ApplicationContext ctx=new ClassPathXmlApplicationContext("spring.xml");// 获取bean对象UserService userService = (UserService) ctx.getBean("userService");User user = new User();user.setName("李四");user.setAccount("222");user.setPassword("123456");user.setStatus(0);userService.add(user);}
}

 运行结果:

当前的目录结构如下: 

至此, AOP演示结束。。。。。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/466818.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Notepad++ 更改字体大小和颜色

前言 在长时间编程或文本编辑过程中&#xff0c;合适的字体大小和颜色可以显著提高工作效率和减少眼睛疲劳。Notepad 提供了丰富的自定义选项&#xff0c;让你可以根据个人喜好调整编辑器的外观。 步骤详解 1. 更改字体大小 打开 Notepad 启动 Notepad 编辑器。 进入设置菜…

香港航空 阿里滑块 acw_sc__v3 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

Unet++改进3:添加NAMAttention注意力机制

本文内容:添加NAMAttention注意力机制 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 识别不太显著的特征是模型压缩的关键。然而,它在革命性的注意机制中尚未得到研究。在这项工作中,我们提出了一种新的基于归一化的注意力模块(NAM),它抑制了较不显著…

WPF+MVVM案例实战(二十二)- 制作一个侧边弹窗栏(CD类)

文章目录 1、案例效果1、侧边栏分类2、CD类侧边弹窗实现1、样式代码实现2、功能代码实现3 运行效果4、源代码获取1、案例效果 1、侧边栏分类 A类 :左侧弹出侧边栏B类 :右侧弹出侧边栏C类 :顶部弹出侧边栏D类 :底部弹出侧边栏2、CD类侧边弹窗实现 1、样式代码实现 在原有的…

汽车广告常见特效处理有哪些?

​汽车广告作为展示汽车性能和外观的重要媒介&#xff0c;常常需要借助特效来增强视觉效果&#xff0c;吸引观众的注意力。以下是一篇关于汽车广告中常见特效处理的文章。 在竞争激烈的汽车市场中&#xff0c;广告不仅是推广产品的工具&#xff0c;更是艺术和科技的结合。特效技…

【CUDA】线程配置

一、 线程层次结构 1.1 认识 GPU 可并行执行工作 Thread&#xff1a;所有线程执行相同的核函数&#xff0c;并行执行 Thread Block&#xff1a;执行在一个Streaming Multiprocessor (SM)&#xff0c;同一个Block中的线程可以协作 线程的集合称为块&#xff0c;块的数量很多…

爬虫-------字体反爬

目录 一、了解什么是字体加密 二. 定位字体位置 三. python处理字体 1. 工具库 2. 字体读取 3. 处理字体 案例1&#xff1a;起点 案例2&#xff1a;字符偏移&#xff1a; 5请求数据 - 发现偏移量 5.4 多套字体替换 套用模板 版本1 版本2 四.项目实战 1. 采集目…

transformer模型写诗词

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

【计算机网络】章节 知识点总结

一、计算机网络概述 1. 计算机网络向用户提供的两个最重要的功能&#xff1a;连通性、共享 2. 因特网发展的三个阶段&#xff1a; 第一阶段&#xff1a;从单个网络 ARPANET 向互联网发展的过程。1983 年 TCP/IP 协议成为 ARPANET 上的标准协议。第二阶段&#xff1a;建成三级…

【微服务】不同微服务之间用户信息的获取和传递方案

如何才能在每个微服务中都拿到用户信息&#xff1f;如何在微服务之间传递用户信息&#xff1f; 文章目录 概述利用微服务网关做登录校验网关转微服务获取用户信息openFeign传递微服务之间的用户信息 概述 要在每个微服务中获取用户信息&#xff0c;可以采用以下几种方法&#…

【p2p、分布式,区块链笔记 Torrent】WebTorrent 的lt_donthave插件

扩展实现 https://github.com/webtorrent/lt_donthave/blob/master/index.js /*! lt_donthave. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */// 导入所需模块 import arrayRemove from unordered-array-remove // 用于从数组中删除元素的函数 i…

兰空图床配置域名访问

图床已经创建完毕并且可以访问了&#xff0c;但是使用IP地址多少还是差点意思&#xff0c;而且不方便记忆&#xff0c;而NAT模式又没法直接像普通服务器一样DNS解析完就可以访问。 尝试了很多办法&#xff0c;nginx配置了半天也没配好&#xff0c;索性直接重定向&#xff0c;反…

Sophos | 网络安全

在 SophosLabs 和 SophosAI 的威胁情报、人工智能和机器学习的支持下&#xff0c;Sophos 提供广泛的高级产品和服务组合&#xff0c;以保护用户、网络和端点免受勒索软件、恶意软件、漏洞利用、网络钓鱼和各种其他网络攻击。Sophos 提供单一的集成式基于云的管理控制台 Sophos …

STM32外设之SPI的介绍

### STM32外设之SPI的介绍 SPI&#xff08;Serial Peripheral Interface&#xff09;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;主要用于EEPROM、FLASH、实时时钟、AD转换器等外设的通信。SPI通信只需要四根线&#xff0c;节约了芯片的管脚&#x…

基于 Transformer 的语言模型

基于 Transformer 的语言模型 Transformer 是一类基于注意力机制&#xff08;Attention&#xff09;的模块化构建的神经网络结构。给定一个序列&#xff0c;Transformer 将一定数量的历史状态和当前状态同时输入&#xff0c;然后进行加权相加。对历史状态和当前状态进行“通盘…

图数据库| 2 、大数据的演进和数据库的进阶——从数据到大数据、快数据,再到深数据

时至今日&#xff0c;大数据已无处不在&#xff0c;所有行业都在经受大数据的洗礼。但同时我们也发现&#xff0c;不同于传统关系型数据库的表模型&#xff0c;现实世界是非常丰富、高维且相互关联的。此外&#xff0c;我们一旦理解了大数据的演进历程以及对数据库进阶的强需求…

深度学习笔记10-多分类

多分类和softmax回归 在多分类问题中&#xff0c;一个样本会被划分到三个或更多的类别中&#xff0c;可以使用多个二分类模型或一个多分类模型&#xff0c;这两种方式解决多分类问题。 1.基于二分类模型的多分类 直接基于二分类模型解决多分类任务&#xff0c;对于多分类中的每…

一篇文章入门docker!

文章目录 DockerUbuntu 下 docker 安装安装docker运行docker Docker的常用命令帮助命令镜像命令容器命令其他常用命令小结 分层理解一、Docker镜像的分层结构二、UnionFS与镜像分层三、镜像层的具体内容四、镜像分层的好处五、容器层与镜像层的关系 如何提交一个自己的镜像 Doc…

鸿蒙(Harmony)实现滑块验证码

在Android和ios两端已经使用的滑块验证码框架还未适配鸿蒙版&#xff0c;于是需要自己去实现类似如下的滑块验证码&#xff1a; 那么实现这样的验证码主要涉及到几个内容&#xff1a; 1、自定义弹窗 2、base64图片转换 3、滑动组件与滑块的联动&#xff0c;以及横移距离转换…

什么是嵌入式操作系统?

什么是嵌入式操作系统? 想象一下&#xff0c;如果一个智能设备&#xff0c;比如你口袋里的智能手机&#xff0c;是一个有头脑的机器人&#xff0c;那么嵌入式操作系统&#xff08;Embedded Operating System&#xff0c;简称EOS&#xff09;就相当于这个机器人的大脑。它告诉机…