Spring事务和事务的传播机制
目录
Spring中事务的实现
MySQL中的事务使用
Spring 编程式事务
TransactionTemplate 编程式事务
TransactionManager编程式事务
Spring声明式事务
@Transactional 参数说明
事务因为程序异常捕获不会自动回滚的解决方案
@Transactional 原理
Spring 事务隔离级别
Spring事务失效的场景
非public修饰的方法
为什么非public修饰的方法使用@Transactional会失效?
timeout超时
代码中有try/catch
调用类内部@Transactional方法
数据库不支持事务
Spring 事务传播机制
事务隔离级别和传播机制有什么区别?
① REQUIRES_NEW: 新建事务执行,如果当前存在事务,把当前事务挂起。
② REQUIRED (默认值):如果当前方法没有事务,新建一个事务,如果已经存在一个事务中,则加入到这个事务中。
③ NESTED(嵌套事务):如果当前存在事务,则在嵌套事务内执行。如果不存在,则执行与PROPAGATION_REQUIRED 类似的操作。
加入事务和嵌套事务有什么区别?
嵌套事务的实现原理:
Spring中事务的实现
Spring中的事务操作分为两类:
- 编程式事务 (手动写代码操作事务)
- 声明式事务(利用注解自动开启和提交事务)
MySQL中的事务使用
事务在MySQL有3个重要的操作:开启事务、提交事务、回滚事务,它们对应的操作命令如下:
-- 开启事务
start transaction;
-- 业务执行-- 提交事务
commit;-- 回滚事务
rollback;
Spring 编程式事务
Spring 手动操作事务和上面MySQL操作事务类似,他也是有3个重要操作步骤:
- 开启事务(获取事务)
- 提交事务
- 回滚事务
编程式事务有两种实现方式
- 使用 TransactionTemplate 对象实现编程式事务
- 使用更加底层的 TransactionManager 对象实现编程式事务
TransactionTemplate 编程式事务
要使用 TransactionTemplate 对象需要先将 TransactionTemplate 注入到当前类中,然后再使用它提供的 execute 方法执行事务并返回相应的执行结果,如果程序在执行途中出现了异常,那么就可以使用代码手动回滚事务,具体实现代码如下:
TransactionManager编程式事务
TransactionManager 实现编程式事务相对麻烦一点,它需要使用两个对象TransactionManager 的子类,加上 TransactionDefinition 事务定义对象,再通过调用TransactionManager的 getTransaction 获取并开启事务,然后调用 TransactionManager 提供的 commit 方法提交事务,或使用它的另一个方法 rollback 回滚事务,它的具体实现代码如下:
SpringBoot内置了两个对象:
- DataSourceTransactionManager: 事务的管理器, 是用来获取事务(开启事务)、提交或回滚事务的。
- TransactionDefinition :事务的属性,在获取事务的时候需要将TransactionDefinition传递进去从而获得一个事务 TransactionStatus。
实现代码如下:
package com.example.demo.controller;import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController // 这是@Controller + @ResponseBody 的结果
//目的是返回非页面数据
@RequestMapping("/user")
public class UserController {//编程式事务@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@Autowiredprivate UserService userService;@RequestMapping("/del")public int del(Integer id) {if (id == null || id <= 0) return 0;TransactionStatus transactionStatus = null;int result = 0;try {// 1. 开启事务transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);// 业务操作 删除用户result = userService.del(id);System.out.println("删除:" + result);dataSourceTransactionManager.commit(transactionStatus); // 提交事务} catch (Exception e) {if (transactionStatus != null) {dataSourceTransactionManager.rollback(transactionStatus); // 回滚事务}}return result;}
}
Spring声明式事务
声明式事务:只需要事务的⽅法上添加@Transactional 注解就可以实现了
⽆需⼿动开启事务和提交事务,添加该注解后实现的效果如下:
- 进⼊⽅法时自动开启事务。
- 方法执行完会自动提交事务。
- 如果中途发⽣了没有处理的异常会自动回滚事务。
@RestController
public class UserController2 {@Autowiredprivate UserService userService;@RequestMapping("/del")@Transactionalpublic int del(Integer id) {if (id == null || id <= 0) return 0;int result = userService.del(id);System.out.println("删除: " + result);// int num = 10 / 0; return result;}
}
如果上面的异常触发,就会导致事务回滚,如果没有,事务则正常提交。
需要注意的一点是:这里的@Transactional 与单元测试中的@Transactional不一样。
单元测试中的@Transactional 是: 无论方法是执行完方法后,一定回滚事务。
@Transactional的作用
@Transactional 可以⽤来修饰方法或类:
- 修饰⽅法时: 只有修饰public⽅法时才⽣效(修饰其他⽅法时不会报错,也不生效)[推荐]
- 修饰类时: 对 @Transactional 修饰的类中所有的public方法都生效.
@Transactional 参数说明
需要注意的是:
@Transactional 在异常被捕获的情况下,不会进行事务自动回滚:
package com.example.demo.controller;import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user2")
public class UserController2 {@Autowiredprivate UserService userService;@RequestMapping("/del")@Transactional()public int del(Integer id) {if (id == null || id <= 0) return 0;int result = userService.del(id);System.out.println("删除: " + result);try {int num = 10 / 0;} catch (Exception e) {e.printStackTrace();}return result;}
}
观察代码运行结果,可以发现:由于异常被程序捕获(try-catch),事务不会进行回滚,数据被删除:
其实这是因为 @Transactional 在底层实现的时候是通过代理类来完成的,代理类会通过反射拿到目标方法,如果目标方法出现异常会进行回滚操作,否则就提交当前事务。
因此,如果我们在程序中显示的捕获异常,那么 @Transactional 里面的代理类就无法捕获到异常,于是就提交了事务。
事务因为程序异常捕获不会自动回滚的解决方案
方案①:将异常重新抛出
对于捕获的异常,事务是会自动回滚的,因此解决方案就是将异常重新抛出:
package com.example.demo.controller;import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user2")
public class UserController2 {@Autowiredprivate UserService userService;@RequestMapping("/del")@Transactional()public int del(Integer id) {if (id == null || id <= 0) return 0;int result = userService.del(id);System.out.println("删除: " + result);try {int num = 10 / 0;} catch (Exception e) {throw e;}return result;}
}
运行结果:
方案②:手动回滚事务
⼿动回滚事务,在⽅法中使⽤ TransactionAspectSupport.currentTransactionStatus() 可
以得到当前的事务,然后设置回滚⽅法 setRollbackOnly 就可以实现回滚了:
@Transactional 原理
@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝,默认情况下会采⽤ JDK 的动态代理,如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。
@Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇到的异常,则回滚事务:
实现细节:
Spring 事务隔离级别
Spring 中事务隔离级别包含以下 5 种:
- Isolation.DEFAULT:以连接的数据库的事务隔离级别为主。
- Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。
- Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。
- Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL默认级别)。
- Isolation.SERIALIZABLE:串⾏化,可以解决所有并发问题,但性能太低。
相比于 MySQL 的事务隔离级别,Spring 的事务隔离级别只是多了⼀个 Isolation.DEFAULT(以数据库的全局事务隔离级别为主)。
Spring 中事务隔离级别只需要设置 @Transactional ⾥的 isolation 属性即可,具体实现代码如下:
Spring事务失效的场景
在开始之前,我们先要明确一个定义,什么叫做“失效”?
本文中的“失效”指的是“失去(它的)功效”,也就是当 @Transactional 不符合我们预期的结果时,我们就可以说 @Transactional 失效了。
那 @Transactional 失效的场景有哪些呢?接下来我们一一来看。
非public修饰的方法
当 @Transactional 修饰的方法为非 public 时,事务就失效了,比如以下代码当遇到异常之后,不能自动实现回滚:
@Transactional
@RequestMapping("/save")
int save(UserInfo userInfo) {// 非空效验if (userInfo == null ||!StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword()))return 0;// 执行添加操作int result = userService.save(userInfo);System.out.println("add 受影响的行数:" + result);int num = 10 / 0; // 此处设置一个异常return result;
}
为什么非public修饰的方法使用@Transactional会失效?
答: 这分为两层原因: 浅层原因 和 深层次原因.
1. 浅层原因
浅层原因是 @Transactional 源码限制了必须是 public 才能执行后续的代理流程,它的部分实现源码如下:
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?>
targetClass) {// Don't allow no-public methods as required.// 非 public 方法,设置为 nul1if(allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// 后面代码省略....
}
2. 深层次原因
深层次的原因 Spring Boot 的动态代理只能代理公共方法,而不能代理私有方法或受保护的方法。
这是因为 Spring 的动态代理是基于 Java 的接口代理机制或者基于 CGLib 库来实现的,而这两种代理方式都只能代理公共方法。
- 接口代理: 当目标类实现了接口时,Spring 使用JDK 动态代理来生成代理对象。JDK 动态代理是通过生成实现目标类接口的匿名类,并将方法调用委托给目标类的实例来实现的。由于接口中的方法都是公共的,所以JDK 动态代理只能代理公共方法。
- CGLib 代理: 当目标类没有实现接门时,Spring 使用 CGLib 动态代理来生成代理对象CGLib 动态代理是通过生成目标类的子类,并将方法调用委托给子类的实例来实现的。然而Java 中的继承要求子类能够继承父类的方法,因此 CGLib 动态代理也只能代理目标类中的公共方法。
timeout超时
当在 @Transactional 上,设置了一个较小的超时时间时,如果方法本身的执行时间超过了设置的 timeout 超时时间,那么就会导致本来应该正常插入数据的方法执行失败,示例代码如下:
@Transactional(timeout = 3) // 超时时间为 3s
@RequestMapping("/save")
int save(UserInfo userInfo) throws InterruptedException {// 非空效验if (userInfo == null ||!StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword()))return 0;int result = userService.save(userInfo);return result;
}
UserService 的 save 方法实现如下:
public int save(UserInfo userInfo) throws InterruptedException {// 休眠 5sTimeUnit.SECONDS.sleep(5);int result = userMapper.add(userInfo);return result;
}
代码中有try/catch
在前面 @Transactional 的执行流程中,我们提到:当方法中出现了异常之后,事务会自动回滚。然而,如果在程序中加了 try/catch 之后,@Transactional 就不会自动回滚事务了,示例代码如下:
@Transactional
@RequestMapping("/save")
public int save(UserInfo userInfo) throws InterruptedException {// 非空效验if (userInfo == null ||!StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword()))return 0;int result = userService.save(userInfo);try {int num = 10 / 0; // 此处设置一个异常} catch (Exception e) {}return result;
}
调用类内部@Transactional方法
当调用类内部的 @Transactional 修饰的方法时,事务是不会生效的,示例代码如下:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class MyService {// 这个outerMethod方法的@Transactional无所谓有没有标注@Transactionalpublic void outerMethod() {// 调用内部方法innerMethod();}@Transactionalpublic void innerMethod() {// 这里的事务可能不会生效// ...}
}
说明:因为 @Transactional 是基于动态代理实现的,而当调用类内部的方法时,不是通过代理对象完成的,而是通过 this 对象实现的,这样就绕过了代理对象,从而事务就失效了。
数据库不支持事务
我们程序中的 @Transactional 只是给调用的数据库发送了:开始事务、提交事务、回滚事务的指令,但是如果数据库本身不支持事务,比如 MySQL 中设置了使用 MyISAM 引擎,那么它本身是不支持事务的,这种情况下,即使在程序中添加了 @Transactional 注解,那么依然不会有事务的行为,这就是巧妇也难为无米之炊吧。
Spring 事务传播机制
Spring 事务传播机制定义了多个包含了事务的⽅法: 相互调用时,事务是如何在这些⽅法间进⾏传递的。
比如有两个⽅法A,B都被 @Transactional 修饰,A⽅法调⽤B⽅法
A方法运行时,会开启⼀个事务.当A调⽤B时,B⽅法本⾝也有事务,此时B⽅法运⾏时,是加⼊A的事务,还是创建⼀个新的事务呢?这个就涉及到了事务的传播机制.
比如公司流程管理
执行任务之前,需要先写执行⽂档,任务执行结束,再写总结汇报。
此时A部门有⼀项⼯作,需要B部门的⽀援,此时B部门是直接使⽤A部门的⽂档,还是新建⼀个⽂档呢?
事务隔离级别和传播机制有什么区别?
事务的隔离级别是保证多个并发事务执行的可控性(稳定性),而事务传播机制是保证一个事务在多个调用方法间的可控性(稳定性)。
事务隔离级别描述的是多个事务同时执行时的某种行为;
而事务传播机制是描述包含了多个事务的方法在相互调用时事务的传播行为。
所以事务隔离级别描述的是纵向事务并发调用时的行为模式,而事务传播机制描述的是横向事务传递时的行为模式,如下图所示:
Spring 事务传播机制包含以下 7 种:
- Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。
- Propagation.SUPPORTS:如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。
- Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。
- Propagation.REQUIRES_NEW:表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。
- Propagation.NOT_SUPPORTED:以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。
- Propagation.NEVER:以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。
- Propagation.NESTED:如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。
以上 7 种传播⾏为,可以根据是否⽀持当前事务分为以下 3 类:
为了加深印象,我们这里就演示其中的三种传播机制:
调用链关系:Controller --> UserService -> LogService
Controller:
UserService:
LogService:
方便演示,这里更改传播机制时候是整个调用链一起修改。
① REQUIRES_NEW: 新建事务执行,如果当前存在事务,把当前事务挂起。
预期运行结果:用户添加成功,日志添加失败。
实际运行结果:没有添加任何记录。
分析:因为没有将程序异常进行处理,导致整条调用链上的事务感知到,从而全部回滚。
改进方法,将异常捕获,进行回滚:
运行结果:符合预期,日志出现回滚,用户加入操作没有回滚。
② REQUIRED (默认值)
:如果当前方法没有事务,新建一个事务,如果已经存在一个事务中,则加入到这个事务中。
预期运行结果:全部事务都进行回滚。
运行结果:全部事务进行回滚。
这里即使我们进行异常处理,还是出现报错的原因是因为:这里使用REQUIRED 是把这些事务看成一个整体,而事务外部觉得不应该回滚,因为没有出现异常,而事务内部进行回滚了,所以这里程序不知道什么情况,所以报500了。
但是如果是外部事务进行回滚,那么内部事务也会进行回滚。(这时候不会报异常)
③ NESTED(嵌套事务):如果当前存在事务,则在嵌套事务内执行。如果不存在,则执行与PROPAGATION_REQUIRED 类似的操作。
执行结果,日志添加失败,用户添加成功。
这里的效果跟REQUIRES_NEW是很像的。
看到这里,可能有人会问:
加入事务和嵌套事务有什么区别?
加入事务 (REQUIRED) 和嵌套事务(NESTED) 都是事务传播机制中的两种传播级别,如果当前不存在事务,那么二者的行为是一致的。但如果当前存在事务:
- 加入事务: 遇到异常时,会回滚全部事务
- 嵌套事务:遇到异常时,回滚部分事务
嵌套事务之所以能回滚部分事务,是因为数据库中存在一个保存点的概念,嵌套事务相对于新建了一个保存点,如果出现异常了,那么只需要回滚到保存点即可,这样就实现了部分事务的回滚。
嵌套事务的实现原理:
嵌套事务之所以能实现部分事务的回滚,是因为在数据库中存在一个保存点(savepoint)的概念,以 MySQL 为例,嵌套事务相当于新建了一个保存点,而滚回时只回滚到当前保存点,因此之前的事务是不受影响的,这一点可以在 MySQL 的官方文档汇总找到相应的资料: https://dev.mysgl.com/doc/refman/5.7/en/savepoint.html
而 REQUIRED 是加入到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,这就是嵌套事务和加入事务的区别。
保存点就像玩通关游戏时的“游戏存档”一样,如果设置了游戏存档,那么即使当前关卡失败了,也能继续上一个存档点继续玩,而不是从头开始玩游戏。
相关文章:

Spring事务和事务的传播机制
目录 Spring中事务的实现 MySQL中的事务使用 Spring 编程式事务 TransactionTemplate 编程式事务 TransactionManager编程式事务 Spring声明式事务 Transactional 参数说明 事务因为程序异常捕获不会自动回滚的解决方案 Transactional 原理 Spring 事务隔离级别 Spring…...

软件开发提效工具——低代码(Low-Code)
目录 一、什么是低代码(Low-Code)? 二、构建轻量化平台 1、软件开发快效率高 2、满足企业的多样化需求 3、轻松与异构系统集成 4、软件维护成本低 5、为企业实现降本增效 三、小结 一、什么是低代码(Low-Code)…...

菜单栏管理软件 Bartender 3 mac中文版功能介绍
Bartender 3 mac是一款菜单栏管理软件,该软件可以将指定的程序图标隐藏起来,需要时呼出即可。 Bartender 3 mac功能介绍 Bartender 3完全支持macOS Sierra和High Sierra。 更新了macOS High Sierra的用户界面 酒吧现在显示在菜单栏中,使其…...

ef core code first pgsql
在使用efcode来操作pgsql的时候,总有些基础配置流程项目建立完之后后面就很少用,总是忘掉,写个文档记忆一下吧。基于net 6.0。 1.创建一个mvc项目和一个EF类库 2.在类库里面安装依赖dll Microsoft.EntityFrameworkCore.Design 需要添加的…...

容器化nacos部署并实现服务发现(gradle)
1.如何容器化部署mysql 2. 如何容器化部署nacos 为不暴露我的服务器地址,本文全部使用localhost来代替服务器地址,所有的localhost都应该调整为你自己的服务器地址。 为不暴露我的服务器地址,本文全部使用localhost来代替服务器地址&#x…...

金融行业如何数字化转型?_光点科技
金融行业的数字化转型涉及技术创新的引入、客户体验的改善、内部流程的优化、安全和合规性的加强以及员工技能和企业文化的转变。 技术创新 包括云计算、人工智能、大数据分析和区块链技术的采用。云计算增强数据处理的灵活性,AI和机器学习在风险评估和欺诈检测方面…...

【LeetCode刷题-滑动窗口】--1695.删除子数组的最大得分
1695.删除子数组的最大得分 注意:子数组为不同元素 方法:滑动窗口 使用变长滑动窗口寻找数组nums中的以每个下标作为结束下标的元素各不相同的最长子数组。用[start,end]表示滑动窗口,初始时startend0,将滑动窗口的右端点end向右…...

iOS OpenGL ES3.0入门实践
一、效果图 入门实践,做的东西比较简单,效果如下: 二、关于顶点坐标和纹理坐标 绘制图片需要设置顶点坐标和纹理坐标并加载像素数据,之所以要指定两组坐标是因为纹理和顶点使用不同的坐标系,就是告诉OpenGL…...

网络基础(一)
文章目录: 计算机网络认识计算机网络背景网络发展认识 “协议” 网络协议初识协议分层OSI七层模型TC/IP 五层(或四层)模型 网络传输基本流程网络传输流程图同局域网的两台主机进行通信跨网络的两台主机进行通信数据包的封装和分用 网络中的地…...

SQLServer添加Oracle链接服务器
又一次在项目中用到了在SQLServer添加Oracle链接服务器,发现之前文章写的也不太好使,那就再总结一次吧。 1、安装OracleClient 安装64位,多数SQLServer是64位,所以OracleClient也安装64位的; 再一个一般安装的Oracl…...

2017年计网408
第33题 假设 OSI 参考模型的应用层欲发送 400B 的数据 (无拆分), 除物理层和应用层之外, 其他各层在封装 PDU 时均引入 20 B 的额外开销, 则应用层数据传输效率约为( )A. 80%B. 83%C. 87%D. 91% 本题考察有关数据包逐层封装的相关概念。我们来一起分析一下。 这是要求大家必须…...

UE5中APlayerController属性与方法列表(翻译中......)
一、属性列表 类型 名称 描述 TObjectPtr< APa... AcknowledgedPawn 用于网络游戏,使客户端可以承认它拥有一个特定的卒。 TArray< FActive... ActiveForceFeedbackEffects TSharedPtr< str... ActiveHapticEffect_Gun TSharedPtr< str..…...

TCP连接保活机制
在TCP连接中有一个保活机制,叫做Keep-Alive,用语言描述就是如下: 在保活时间内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔(保活时间间隔),发…...

centos安装mysql8.0.20、tar包安装方式
基础环境centos7.5,mysql版本8.0.20,通过tar包安装,安装路径/usr/local。 mysql官网:https://dev.mysql.com/downloads/mysql/ wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.x…...

k8s yaml文件含义
文章目录 1、YAML的文件格式和注意事项2、YAML各个字段含义 1、YAML的文件格式和注意事项 不支持制表符tab键缩进,需要使用空格缩进,使用缩进表示层级关系通常开头缩进2个空格,缩进的空格数不重要,只要相同层级的元素左对齐即可字…...

ProEasy机器人:运动+通讯相关说明
----------------机械手运动------- --常用指令:MovP弧线运动、MovL直线运动 MovP(1) --弧线轨迹运动到一号点 MovP(2) --弧线轨迹运动到二号点 MovL(1) --直线轨迹运动到一号点 MovL(2) --直线轨迹运…...

Visual Studio Code 配置 C/C++ 开发环境的最佳实践(VSCode + Clangd + CMake)
Visual Studio Code 配置 C/C 开发环境的最佳实践(VSCode Clangd CMake) 知乎原文参考地址1 与 VSCode 官方文档配置 相比拥有的优势 Clangd 具有更优秀的性能,微软官方 Cpptools 的代码提示功能有明显延迟Clangd 提供更精准的「转到定义」、「重命名符号」、「…...

年产200万件的超级工厂投产!巨头「闭环」汽车电子全产业链
随着汽车电动化程度的提升,汽车电子部件占整车成本比重逐步升高,已经从2012年的25%上升到2021年的55%。 且汽车电子电气架构向整车集中演进,智能汽车已经进入了软件及数据定义时代,底层硬件打破了过去几十年围绕特定应用不断增加…...

智能穿戴AR眼镜主板方案定制_MTK平台AR智能眼镜PCB板开发
AR智能眼镜,是采用了多种技术实现增强现实效果,是将虚拟信息和现实场景相结合的智能设备。 AR智能眼镜硬件上,包括多个传感器、显示装置和处理器等。其中,传感器用于捕捉用户的动作和环境信息,如摄像头、陀螺仪、加速…...

【入门Flink】- 11Flink实现动态TopN
基本处理函数(ProcessFunction) stream.process(new MyProcessFunction())方法需要传入一个 ProcessFunction 作为参数,ProcessFunction 不是接口 , 而是一个抽象类 ,继承了AbstractRichFunction,所有的处…...

现在做跨境电商还需要全球代理IP吗?全球代理IP哪家靠谱?
随着全球互联网的发展,电商平台的发展和跨境贸易的便利化,跨境电商在过去几年中也一直呈现增长趋势,吸引了越来越多的企业和个体创业者入行。 然而,行业竞争也在不断加剧,跨境电商面临更多的越来越多的挑战࿰…...

微服务的常用组件
1、注册中心组件 Eureka、Nacos、Zookeeper、Consul 2、负载均衡组件 Ribbon 3、远程调用组件 OpenFeign 4、网关组件 Zuul、Gateway 5、服务保护组件 Hystrix、Sentinel 6、服务配置管理组件 SpringCloudConfig、Nacos、Apollo(阿波罗)配置中…...

Android问题笔记四十五:解决SeekBar操作thumb周围产生的圆形阴影/灰色阴影/白色圆圈的解决办法
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列点击跳转>ChatGPT和AIGC 👉关于作者 专…...

AI从入门到精通,什么是LLMs大型语言模型?
大型语言模型是指由大量文本数据训练而成的自然语言处理模型,它可以生成高质量的文本内容,并能够理解和回答人类提出的问题。 这种模型通常基于深度学习技术,如循环神经网络(RNN)或变换器(Transformer&…...

优测云测试平台 | 有效的单元测试(下)
接着上一篇内容,我们继续~ 四、测试的目标之三:快速反馈 测试的快速反馈有两个方面的含义: 1.测试运行要快速出结果。 2.当测试失败时,要能快速定位失败原因。 测试运行效率决定了开发的工作周期运转的快慢。在理想的 TDD 模型中&#x…...

CUDA安装
在cmd中输入nvidia-smi。显示CUDA Version:12.3,所以只能下载小于等于12.3的版本。如下图: 进这个网址:https://developer.nvidia.com/cuda-toolkit-archive 选择一个版本下载。 选择完后之后这样选择: 最后点击下载即…...

【XTDrone Ubuntu18.04】XTDrone + Ubuntu18.04 + PX4 安装过程
重新配置所有的软件 卸载之前安装的ROS GAZEBO 记得把/home下的.ros和.gazebo也删除,删就删干净 参考链接:ROS的卸载与安装 血泪总结!亲测有效 卸载ROS方法 正式安装 安装依赖 sudo apt install ninja-build exiftool ninja-build protobuf…...

网站使用什么协议比较好
网站协议大多数使用HTTP和HTTPS HTTP协议,超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议。 HTTP是应用层协议,同其他应用层协议一样,是为了实现某一类具体应用的协议&…...

18. 机器学习——集成学习
机器学习面试题汇总与解析——集成学习 本章讲解知识点 什么是集成学习AdaBoost梯度提升树(Gradient Boosting Decision Tree, GBDT)随机森林(Random Forest,简称RF)XGBoostLightGBM本专栏适合于Python已经入门的学生或人士,有一定的编程基础。 本专栏适合于算法工程师、机器…...

SimaPro生命周期评估建模与碳足迹分析流程
SimaPro以系统和透明的方式轻松建模和分析复杂的生命周期,通过确定供应链中每个环节的热点,从原材料的提取到制造,分销,使用和处置,衡量所有生命周期阶段的产品和服务对环境的影响。SimaPro是过去25年评估生命周期的最…...