Spring源码-从源码层面讲解传播特性
传播特性:service:REQUIRED,dao:REQUIRED
两个都是required使用的是同一个事务,正常情况,在service提交commit
<tx:advice id="myAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="checkout" propagation="REQUIRED" /><tx:method name="updateStock" propagation="REQUIRED" /></tx:attributes></tx:advice>
service:
public void checkout(String username,int id){try {bookDao.updateStock(id);} catch (Exception e) {e.printStackTrace();}}
dao:
public void updateStock(int id){String sql = "update book_stock set stock=stock-1 where id=?";jdbcTemplate.update(sql,id);for (int i = 1 ;i>=0 ;i--)System.out.println(10/i);}
dao层抛出异常导致

service层事务:外层开始没有事务所以这里是true

dao内层事务因为传播特性是required所以复用的是外层service事务


newSynchronization变为false

old是外层service,this是当前dao的

这里执行的sql不会实际生效因为没有commit,下面for会有异常 看看后续怎么处理异常再事务


completeTransactionAfterThrowing异常回滚


先处理回滚的规则,就是事务注解里的rollbackFor,rollbackForClassName,noRollbackFor,noRollbackForClassName属性如果没有设置就会调用父类的rollbackOn

super.rollbackOn(ex);

开始completeTransactionAfterThrowing的txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());


把外层事务信息恢复回去

开始打印异常信息

在service层捕获了异常没有抛 所以外层事务不回滚

在这里完成回滚

UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only异常在这里抛出

数据库数据不会被修改
service:REQUIRED,dao:NESTED
<tx:advice id="myAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="checkout" propagation="REQUIRED" /><tx:method name="updateStock" propagation="NESTED" /></tx:attributes></tx:advice>
PROPAGATION_NESTED为事务设置一个回退点


设置mysql连接的保存点

保存点设置完成

createAndHoldSavepoint:140, AbstractTransactionStatus (org.springframework.transaction.support)
handleExistingTransaction:490, AbstractPlatformTransactionManager (org.springframework.transaction.support)
getTransaction:356, AbstractPlatformTransactionManager (org.springframework.transaction.support)
createTransactionIfNecessary:588, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:367, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:125, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:100, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:721, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
updateStock:-1, BookDao$$EnhancerBySpringCGLIB$$421d7dae (com.mashibing.tx.xml.dao)
checkout:25, BookService (com.mashibing.tx.xml.service)
invoke:-1, BookService$$FastClassBySpringCGLIB$$66a1e40d (com.mashibing.tx.xml.service)
invoke:218, MethodProxy (org.springframework.cglib.proxy)
invokeJoinpoint:802, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceedWithInvocation:-1, 1079125839 (org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda$47)
invokeWithinTransaction:374, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:125, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:100, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:721, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
checkout:-1, BookService$$EnhancerBySpringCGLIB$$d6fab840 (com.mashibing.tx.xml.service)
main:17, TxTest (com.mashibing.tx.xml)
代码执行到这里没有新建连接,用的是外层方法事务和连接。

在mysql中保存点的使用:
stock=100 设置保存点p1 后面会回滚到P1 就能实现一个事务中部分成功部分失败。stock最后变为97,说明前三个修改语句生效,后三个失败,保存点的作用就是保存保存点之前的sql生效。后边的会回滚不会实际生效

执行dao的内层方法抛异常,此时事务有保存点在这里执行回滚保存点的操作,并且把rollbackOnly变为false,来进行重置保存点。

外层service捕获异常,继续后续执行

直接执行下面的commit,上面的两个if进不去

此时执行的是service的外层事务,没有保存点直接执行docommit,外层方法正常提交结束。


service:REQUIRED,dao:REQUIRED_NEW
BookDao的内层方式这里能获取到threadlocal里的连接。

doGetTransaction:275, DataSourceTransactionManager (org.springframework.jdbc.datasource)
getTransaction:349, AbstractPlatformTransactionManager (org.springframework.transaction.support)
createTransactionIfNecessary:588, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:367, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:125, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:100, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:721, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
updateStock:-1, BookDao$$EnhancerBySpringCGLIB$$46f7c792 (com.mashibing.tx.xml.dao)
checkout:25, BookService (com.mashibing.tx.xml.service)
invoke:-1, BookService$$FastClassBySpringCGLIB$$66a1e40d (com.mashibing.tx.xml.service)
invoke:218, MethodProxy (org.springframework.cglib.proxy)
invokeJoinpoint:802, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceedWithInvocation:-1, 1988939205 (org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda$47)
invokeWithinTransaction:374, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:125, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:100, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:721, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
checkout:-1, BookService$$EnhancerBySpringCGLIB$$dbd50224 (com.mashibing.tx.xml.service)
main:17, TxTest (com.mashibing.tx.xml)
存在外部事务

当前dao是PROPAGATION_REQUIRES_NEW,先挂起外层事务

SuspendedResourcesHolder 挂起
/*** 有些传播机制需要挂起当前的事务,比如NOT_SUPPORTED,REQUIRES_NEW首先会清除所有线程相关的同步状态,如果当前事务存在的话,就进行一些属性的清除,比如清空连接持有器,清空线程私有变量的同步状态,* 最后把当前事务清除的属性保存到一个SuspendedResourcesHolder里,以便于恢复的时候设置会去*/@Nullableprotected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {// 判断当前的线程变量中有没有激活的事物,有需要清空线程变量if (TransactionSynchronizationManager.isSynchronizationActive()) {List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();try {Object suspendedResources = null;if (transaction != null) {//挂起的资源,连接持有器suspendedResources = doSuspend(transaction);}// 获取当前事务名称String name = TransactionSynchronizationManager.getCurrentTransactionName();// 清空线程变量TransactionSynchronizationManager.setCurrentTransactionName(null);// 获取出只读事务的名称boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();// 清空线程变量TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);// 获取已存在事务的隔离级别Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();// 清空隔离级别TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);// 判断当前事务激活状态boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();// 清空标记TransactionSynchronizationManager.setActualTransactionActive(false);// 把上诉从线程变量中获取出来的存在事务属性封装为挂起的事务属性返回出去return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);}catch (RuntimeException | Error ex) {// doSuspend failed - original transaction is still active...doResumeSynchronization(suspendedSynchronizations);throw ex;}}else if (transaction != null) {// Transaction active but no synchronization active.Object suspendedResources = doSuspend(transaction);return new SuspendedResourcesHolder(suspendedResources);}else {// Neither transaction nor synchronization active.return null;}}
doSuspend
清空连接持有器
/*** 实际挂起资源的方法* @param transaction the transaction object returned by {@code doGetTransaction}* @return*/@Overrideprotected Object doSuspend(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// 清空连接持有器txObject.setConnectionHolder(null);// 解绑线程私有的资源return TransactionSynchronizationManager.unbindResource(obtainDataSource());}
实际处理挂起事务 清除threadlocal的副本

被挂起的历史事务相关属性信息

doBegin(transaction, definition);// 开启事务和连接
开启连接和事务
service层的事务和dao层的不关联,各自有各自的事务和数据库连接,内层回滚不影响外层的了
通过数据源获取一个数据库连接对象 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">// 通过数据源获取一个数据库连接对象 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">Connection newCon = obtainDataSource().getConnection();//从DruidDataSource获取连接if (logger.isDebugEnabled()) {logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");}// 把我们的数据库连接包装成一个ConnectionHolder对象 然后设置到我们的txObject对象中去txObject.setConnectionHolder(new ConnectionHolder(newCon), true);。。。。。。// 关闭自动提交 如果不i关闭每次sql执行就自动提交了if (con.getAutoCommit()) {//设置需要恢复自动提交txObject.setMustRestoreAutoCommit(true);if (logger.isDebugEnabled()) {logger.debug("Switching JDBC Connection [" + con + "] to manual commit");}// 关闭自动提交con.setAutoCommit(false);}。。。。。。// Bind the connection holder to the thread.// 绑定我们的数据源和连接到我们的同步管理器上,把数据源作为key,数据库连接作为value 设置到线程变量中if (txObject.isNewConnectionHolder()) {// 将当前获取到的连接绑定到当前线程 数据源和连接持久器进行绑定TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());}
后续执行dao层抛出异常
completeTransactionAfterThrowing:668, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:379, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:125, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:100, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:721, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
updateStock:-1, BookDao$$EnhancerBySpringCGLIB$$46f7c792 (com.mashibing.tx.xml.dao)
checkout:25, BookService (com.mashibing.tx.xml.service)
invoke:-1, BookService$$FastClassBySpringCGLIB$$66a1e40d (com.mashibing.tx.xml.service)
invoke:218, MethodProxy (org.springframework.cglib.proxy)
invokeJoinpoint:802, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceedWithInvocation:-1, 1988939205 (org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda$47)
invokeWithinTransaction:374, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:125, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:100, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:199, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:780, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:721, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
checkout:-1, BookService$$EnhancerBySpringCGLIB$$dbd50224 (com.mashibing.tx.xml.service)
main:17, TxTest (com.mashibing.tx.xml)



/*** 真正回滚的处理方法,也就是获取JDBC连接,然后回滚* @param status the status representation of the transaction*/@Overrideprotected void doRollback(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();if (status.isDebug()) {logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");}try {// jdbc的回滚con.rollback();}catch (SQLException ex) {throw new TransactionSystemException("Could not roll back JDBC transaction", ex);}}
cleanupAfterCompletion
/*** 回滚后的处理工作,如果是新的事务同步状态的话,要把线程的同步状态清除了,* 如果是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等。* 如果有挂起的事务,还要把这个事务给恢复,其实就是把属性设置回去** Clean up after completion, clearing synchronization if necessary,* and invoking doCleanupAfterCompletion.* @param status object representing the transaction* @see #doCleanupAfterCompletion*/private void cleanupAfterCompletion(DefaultTransactionStatus status) {// 设置完成状态status.setCompleted();if (status.isNewSynchronization()) {// 线程同步状态清除TransactionSynchronizationManager.clear();}// 如果是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等if (status.isNewTransaction()) {doCleanupAfterCompletion(status.getTransaction());}// 有挂起的事务要恢复if (status.getSuspendedResources() != null) {if (status.isDebug()) {logger.debug("Resuming suspended transaction after completion of inner transaction");}Object transaction = (status.hasTransaction() ? status.getTransaction() : null);// 结束之前事务的挂起状态resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());}}
resume恢复外层事务到本地线程,如果service方法有多个事务dao执行完一个dao需要将service的事务恢复到线程
/*** 如果前面有事务被挂起,现在就要回复,其实就是把一些属性设置回去** Resume the given transaction. Delegates to the {@code doResume}* template method first, then resuming transaction synchronization.* @param transaction the current transaction object* @param resourcesHolder the object that holds suspended resources,* as returned by {@code suspend} (or {@code null} to just* resume synchronizations, if any)* @see #doResume* @see #suspend*/protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)throws TransactionException {// 设置属性和状态if (resourcesHolder != null) {Object suspendedResources = resourcesHolder.suspendedResources;if (suspendedResources != null) {doResume(transaction, suspendedResources);}List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;//如果有挂起同步器的话要设置线程私有变量的值为挂起事务的相关属性if (suspendedSynchronizations != null) {TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);doResumeSynchronization(suspendedSynchronizations);}}}
service中对异常catch后续就不会处理异常 直接commit
public void checkout(String username,int id){try {bookDao.updateStock(id);} catch (Exception e) {e.printStackTrace();}}

1.如果service不catch异常会继续向外抛,最终会导致service层也会回滚 ,如此一来,service和dao一共回滚两次;即dao抛出没捕获,dao回滚,此时service捕获了就不回滚,没捕获也会回滚;
2.如果外层有异常抛出,内层正常执行,外层不会导致内层回滚,内层会影响外层,外层不会影响内层;即内外两层是不同事务,内层提交过了,外层有异常没捕获,外层事务回滚,此时内层事务不受影响
相关文章:
Spring源码-从源码层面讲解传播特性
传播特性:service:REQUIRED,dao:REQUIRED 两个都是required使用的是同一个事务,正常情况,在service提交commit <tx:advice id"myAdvice" transaction-manager"transactionManager"><tx:attributes&…...
Rust调用tree-sitter解析C语言
文章目录 一、Rust 调用 tree-sitter 解析 C 语言代码1. 设置 Rust 项目2. 添加 tree-sitter 依赖3. 编写 Rust 代码4. 运行程序5. 编译出错 二、解决步骤1. 添加 tree-sitter 构建依赖2. 添加 tree-sitter-c 源代码3. 修改 build.rs 以编译 tree-sitter-c 库4. 修改 Cargo.tom…...
奇瑞汽车—经纬恒润 供应链技术共创交流日 成功举办
2024年9月12日,奇瑞汽车—经纬恒润技术交流日在安徽省芜湖市奇瑞总部成功举办。此次盛会标志着经纬恒润与奇瑞汽车再次携手,深入探索汽车智能化新技术的前沿趋势,共同开启面向未来的价值服务与产品新篇章。 面对全球汽车智能化浪潮与产业变革…...
vue3 TagInput 实现
效果 要实现类似于下面这种效果 大致原理 其实是很简单的,我们可以利用 element-plus 组件库里的 el-tag 组件来实现 这里我们可以将其抽离成一个公共的组件,那么现在有一个问题就是通讯问题 这里我们可以利用父子组件之间的通讯,利用 v-model 来实现,父组件传值,子组…...
mysql中的json查询
首先来构造数据 查询department里面name等于研发部的数据 查询语句跟普通的sql语句差不多,也就是字段名要用到path表达式 select * from user u where u.department->$.name 研发部 模糊查询 select * from user u where u.department->$.name like %研发%…...
Etcd权限认证管理
1 查看是否开启权限认证 ctl auth status 2 开启权限认证 ctl auth enable。开启后每一条命令都要加上用户 --userroot:root(root默认最高权限) 3 创建其他用户 ctl user add user1 --user用户名:密码 4 创建角色 ctl role add testR --user 5 为角色添加权限 ctl role g…...
图文组合商标部分驳回后优化后初审通过!
这几天以前有个企业的商标初审下来了,以前是加了图形个别部分没有通过初审,后面是把图形去掉重新用文字申请下来初审。 图形与文字同时申请,会分别审查有一个元素过不了,整体就会过不了,所以平常就会建议分开申请注册商…...
【最新华为OD机试E卷-支持在线评测】爱吃蟠桃的孙悟空(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)
🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…...
BUUCTF [SCTF2019]电单车详解两种方法(python实现绝对原创)
使用audacity打开,发现是一段PT2242 信号 PT2242信号 有长有短,短的为0,长的为1化出来 这应该是截获电动车钥匙发射出的锁车信号 0 01110100101010100110 0010 0前四位为同步码0 。。。中间这20位为01110100101010100110为地址码0010为功…...
Apache James配置连接达梦数据库
项目场景: Apache James配置连接达梦数据库,其他配置中不存在的数据库也可参考此方案。 配置步骤 1、把需要的jar包导入到James 把DmJdbcDriver18.jar复制到下面lib目录下 james-2.3.2\lib 2、 修改连接配置 james-2.3.2\apps\james\SAR-INF\confi…...
Java实现栈
一、栈Stack 1.1 概念 一种特殊的线性表,只允许在固定的一段进行插入和删除元素操作。进行数据的插入和删除操作的一段称为栈顶,另一端称为栈低。栈中的元素遵循后进先出 LIFO(Last In First Out)的原则。 进栈 出栈 举例:在word中…...
数据结构—栈
栈 概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈:栈…...
服务设计原则介绍
在Java或任何软件开发中,设计服务时遵循一些核心原则是非常重要的,这些原则不仅有助于构建高质量、可维护的软件系统,还能提高系统的可扩展性和可重用性。以下是一些关键的服务设计原则: 单一职责原则(SingleResponsib…...
【Qualcomm】高通SNPE框架的使用 | 原始模型转换为量化的DLC文件 | 在Android的DSP端运行模型
目录 ① 激活snpe环境 ② 设置环境变量 ③ 模型转换 ④ run 首先,默认SNPE工具已经下载并且Setup相关工作均已完成。同时,拥有原始模型文件,本文使用的模型文件为SNPE 框架示例的inception_v3_2016_08_28_frozen.pb文件。image_file_list…...
爬虫的流程
爬虫的流程 获取网页提取信息保存数据自动化程序能爬怎样的数据 获取网页 获取网页就是获取网页的源代码,源代码里包含了网页的部分有用信息,所以只要把源代码获取下来,就可以从中提取想要的信息浏览器访问网页的本质:浏览器向服…...
Git之如何删除Untracked文件(六十八)
简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【…...
k8s集群自动化管理
项目地址 https://github.com/TimeBye/kubeadm-ha准备安装包 # 离线安装环境 curl -LO https://oss.choerodon.com.cn/kubeadm-ha/kubeadm-ha-base-amd64.tar # 集群运行所需的镜像 curl -LO https://oss.choerodon.com.cn/kubeadm-ha/kubernetes-1.30.2-images-amd64.tgz # …...
yum库 docker的小白安装教程(附部分问题及其解决方案)
yum库 首先我们安装yum 首先在控制台执行下列语句 首先切换到root用户,假如已经是了就不用打下面的语句 su root #使用国内的镜像,不执行直接安装yum是国外的,那个有问题 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.al…...
python如何实现日期加减
首先通过import datetime,导入日期处理库。 然后把日期转化成datetime标准格式,使用datetime.datetime.strptime()方法将字符串格式的时间转化为标准格式。 其中"%Y/%m/%d %H:%M:%S"为time字符串的时间格式:Y为年,m为月…...
springboot实战学习笔记(4)(Spring Validation参数校验框架、全局异常处理器)
接着上篇博客学习。上篇博客是已经基本完成用户模块的注册接口的开发。springboot实战学习笔记(3)(Lombok插件、postman测试工具、MD5加密算法、post请求、接口文档、注解、如何在IDEA中设置层级显示包结构、显示接口中的方法)-CSDN博客本篇博客主要是关…...
AI 开发实战:技术决策为什么总失忆,决策日志可以怎么做
AI 开发实战:技术决策为什么总失忆,决策日志可以怎么做 一、这个问题为什么值得专门拿出来做? 在 AI 工程落地里,真正拖慢团队的往往不是模型本身,而是流程和协作方式没有跟上。 围绕“技术决策为什么总失忆࿰…...
连续使用 OpenClaw 50 天后,我总结了 3 个核心工作流和 5 个血泪教训
🔥 连续使用 OpenClaw 50 天后,我总结了 3 个核心工作流和 5 个血泪教训AI 不会取代你,但会用 AI 的人会取代你——这句话说烂了,但 50 天后我才真正明白它的意思。01 上周五下午 5 点,同事都在加班,我先走…...
告别沉闷AI工具:像素时装锻造坊带你体验RPG游戏式图像生成
告别沉闷AI工具:像素时装锻造坊带你体验RPG游戏式图像生成 1. 引言:当AI图像生成遇上复古RPG 你是否厌倦了传统AI工具单调的黑色界面和机械化的操作流程?像素时装锻造坊(Pixel Fashion Atelier)彻底改变了这一现状。…...
【稀缺预警】Python 3.14 JIT编译器深度剖析:3类隐性CPU浪费模式+2套自动降本脚本(附真实AWS账单对比图)
第一章:Python 3.14 JIT编译器的演进逻辑与成本敏感性定位Python 3.14 并非官方发布的正式版本(截至2024年,CPython最新稳定版为3.12,3.13处于预发布阶段),但本章以假设性技术前瞻视角,探讨若Py…...
墨语灵犀效果展示:康沃尔语复兴运动口号→中文新文化运动风格译文
墨语灵犀效果展示:康沃尔语复兴运动口号→中文新文化运动风格译文 1. 翻译效果惊艳呈现 墨语灵犀作为一款融合古典美学与现代AI技术的深度翻译工具,在语言转换过程中展现出令人惊叹的文化适应能力。本次展示以康沃尔语复兴运动口号为源文本,…...
深入解析GD32/STM32 PWM中断:中央对齐模式的应用与实现
1. PWM中断与中央对齐模式的核心概念 第一次接触PWM中断时,我盯着示波器上跳动的波形发愣——明明配置了中断,为什么触发时机总是不对?后来才发现是计数模式没选对。中央对齐模式(Center-Aligned Mode)在电机控制、LED…...
毕业季求生指南:用百考通AI重塑你的论文写作全流程
深夜的电脑屏幕前,面对空白的文档和堆积如山的文献,你是否感到无从下手?当查重率居高不下、导师的修改意见密密麻麻时,是否渴望一种更智能的解决方案?本文将为你揭示一个学术写作的新可能。 01 开题之困:从…...
Python自动化爬取企查查企业工商信息的实战技巧
1. Python爬取企查查数据的核心思路 企查查作为国内权威的企业信息查询平台,包含了大量有价值的工商注册信息。对于金融、证券行业的从业者来说,经常需要批量获取这些数据进行分析。手动一个个查询不仅效率低下,还容易出错。这时候Python自动…...
破解除密!ncmdumpGUI让你的NCM音乐文件重获自由
破解除密!ncmdumpGUI让你的NCM音乐文件重获自由 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 当你精心收藏的数百首网易云音乐歌曲,在…...
AUTOSAR CANFM模块中,BusOff恢复的50ms和1000ms周期到底怎么来的?底层驱动配置详解
AUTOSAR CANFM模块中BusOff恢复时序的硬件级解析 在车载ECU开发中,CAN总线通信的可靠性直接关系到整车功能安全。当节点因连续错误进入BusOff状态时,AUTOSAR标准定义的50ms快恢复周期和1000ms慢恢复周期并非随意设定,而是源于CAN控制器硬件特…...
