当前位置: 首页 > news >正文

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&#xff1a;REQUIRED&#xff0c;dao:REQUIRED 两个都是required使用的是同一个事务&#xff0c;正常情况&#xff0c;在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日&#xff0c;奇瑞汽车—经纬恒润技术交流日在安徽省芜湖市奇瑞总部成功举办。此次盛会标志着经纬恒润与奇瑞汽车再次携手&#xff0c;深入探索汽车智能化新技术的前沿趋势&#xff0c;共同开启面向未来的价值服务与产品新篇章。 面对全球汽车智能化浪潮与产业变革…...

vue3 TagInput 实现

效果 要实现类似于下面这种效果 大致原理 其实是很简单的,我们可以利用 element-plus 组件库里的 el-tag 组件来实现 这里我们可以将其抽离成一个公共的组件,那么现在有一个问题就是通讯问题 这里我们可以利用父子组件之间的通讯,利用 v-model 来实现,父组件传值,子组…...

mysql中的json查询

首先来构造数据 查询department里面name等于研发部的数据 查询语句跟普通的sql语句差不多&#xff0c;也就是字段名要用到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…...

图文组合商标部分驳回后优化后初审通过!

这几天以前有个企业的商标初审下来了&#xff0c;以前是加了图形个别部分没有通过初审&#xff0c;后面是把图形去掉重新用文字申请下来初审。 图形与文字同时申请&#xff0c;会分别审查有一个元素过不了&#xff0c;整体就会过不了&#xff0c;所以平常就会建议分开申请注册商…...

【最新华为OD机试E卷-支持在线评测】爱吃蟠桃的孙悟空(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…...

BUUCTF [SCTF2019]电单车详解两种方法(python实现绝对原创)

使用audacity打开&#xff0c;发现是一段PT2242 信号 PT2242信号 有长有短&#xff0c;短的为0&#xff0c;长的为1化出来 这应该是截获电动车钥匙发射出的锁车信号 0 01110100101010100110 0010 0前四位为同步码0 。。。中间这20位为01110100101010100110为地址码0010为功…...

Apache James配置连接达梦数据库

项目场景&#xff1a; Apache James配置连接达梦数据库&#xff0c;其他配置中不存在的数据库也可参考此方案。 配置步骤 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 概念 一种特殊的线性表&#xff0c;只允许在固定的一段进行插入和删除元素操作。进行数据的插入和删除操作的一段称为栈顶&#xff0c;另一端称为栈低。栈中的元素遵循后进先出 LIFO(Last In First Out)的原则。 进栈 出栈 举例&#xff1a;在word中&#xf…...

数据结构—栈

栈 概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&#xff1a;栈…...

服务设计原则介绍

在Java或任何软件开发中&#xff0c;设计服务时遵循一些核心原则是非常重要的&#xff0c;这些原则不仅有助于构建高质量、可维护的软件系统&#xff0c;还能提高系统的可扩展性和可重用性。以下是一些关键的服务设计原则&#xff1a; 单一职责原则&#xff08;SingleResponsib…...

【Qualcomm】高通SNPE框架的使用 | 原始模型转换为量化的DLC文件 | 在Android的DSP端运行模型

目录 ① 激活snpe环境 ② 设置环境变量 ③ 模型转换 ④ run 首先&#xff0c;默认SNPE工具已经下载并且Setup相关工作均已完成。同时&#xff0c;拥有原始模型文件&#xff0c;本文使用的模型文件为SNPE 框架示例的inception_v3_2016_08_28_frozen.pb文件。image_file_list…...

爬虫的流程

爬虫的流程 获取网页提取信息保存数据自动化程序能爬怎样的数据 获取网页 获取网页就是获取网页的源代码&#xff0c;源代码里包含了网页的部分有用信息&#xff0c;所以只要把源代码获取下来&#xff0c;就可以从中提取想要的信息浏览器访问网页的本质&#xff1a;浏览器向服…...

Git之如何删除Untracked文件(六十八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…...

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用户&#xff0c;假如已经是了就不用打下面的语句 su root #使用国内的镜像&#xff0c;不执行直接安装yum是国外的&#xff0c;那个有问题 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.al…...

python如何实现日期加减

首先通过import datetime&#xff0c;导入日期处理库。 然后把日期转化成datetime标准格式&#xff0c;使用datetime.datetime.strptime()方法将字符串格式的时间转化为标准格式。 其中"%Y/%m/%d %H:%M:%S"为time字符串的时间格式&#xff1a;Y为年&#xff0c;m为月…...

springboot实战学习笔记(4)(Spring Validation参数校验框架、全局异常处理器)

接着上篇博客学习。上篇博客是已经基本完成用户模块的注册接口的开发。springboot实战学习笔记&#xff08;3&#xff09;(Lombok插件、postman测试工具、MD5加密算法、post请求、接口文档、注解、如何在IDEA中设置层级显示包结构、显示接口中的方法)-CSDN博客本篇博客主要是关…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...