详解Java之Spring框架中事务管理的艺术

第1章:引言

大家好,我是小黑,咱们今天聊聊Spring框架中的事务管理。不管是开发小型应用还是大型企业级应用,事务管理都是个不可避免的话题。那么,为什么事务管理这么重要呢?假设在银行系统中转账时,钱从A账户扣了,但没到B账户,这种情况就是事务管理处理不当的后果。显然,我们需要一种机制来确保数据的完整性和一致性。

Spring框架为此提供了一套优雅的事务管理机制,不仅强大,而且相对容易理解和实现。

第2章:事务管理基础

在深入Spring的事务管理之前,咱们先来搞清楚几个基本概念。事务,简单来说,就是一系列操作,要么全部成功,要么全部失败。这就涉及到了ACID原则:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

  • 原子性:事务中的所有操作要么全部完成,要么全部不做。
  • 一致性:事务必须使数据库从一个一致性状态转移到另一个一致性状态。
  • 隔离性:事务的执行不应该被其他事务干扰。
  • 持久性:事务一旦提交,其结果就是永久性的。

在Java世界里,事务管理最初是通过JDBC来实现的。但这种方式很快就显得力不从心,因为它需要程序员手动管理很多细节,容易出错。而Spring提供了一种声明式的事务管理方法,极大地简化了事务的处理方式。那么,Spring是怎么做到的呢?让小黑来给大家展示一下。

import org.springframework.transaction.annotation.Transactional;

public class TransferService {

    @Transactional
    public void transferMoney(String fromAccountId, String toAccountId, Double amount) {
        // 这里是一些转账的业务逻辑
        // 比如,从一个账户扣款,向另一个账户存款
    }
}

在这段代码里,@Transactional 注解是Spring事务管理的核心。只要在方法上加上这个注解,Spring就会自动处理这个方法的事务。如果方法成功执行完毕,事务就会被提交;如果出现异常,事务就会回滚。这就是声明式事务管理的魅力所在:简单、直观、易于理解和使用。

相比之下,传统的事务管理方式则需要咱们手动控制事务的每个阶段,比如开始事务、提交事务或回滚事务。这不仅代码量大,而且容易出错。小黑来给大家看一个传统的JDBC事务管理示例:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TraditionalTransaction {

    public void transferMoney(String fromAccountId, String toAccountId, Double amount) {
        Connection conn = null;
        try {
            conn = getConnection(); // 获取数据库连接
            conn.setAutoCommit(false); // 开始事务

            // 执行一系列数据库操作
            // ...

            conn.commit(); // 提交事务
        } catch (SQLException e) {
            if (conn != null) {
                try {
                    conn.rollback(); // 出错时回滚事务
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close(); // 关闭连接
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private Connection getConnection() {
        // 这里是获取数据库连接的代码
        return null;
    }
}

从上面的例子可以看出,传统的方式让事务管理变得繁琐而且易出错。而Spring的声明式事务管理则大大简化了这一过程。

第3章:Spring框架中的事务抽象

事务抽象的关键组件

Spring事务抽象的核心是PlatformTransactionManager接口。这个接口为不同的事务管理策略提供了一个标准化的方法。不同的数据库和持久化框架(比如JDBC、Hibernate)都有对应的实现。

来看看PlatformTransactionManager的一个基本示例:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class TransactionManagerExample {

    private PlatformTransactionManager transactionManager;

    public void performTransaction() {
        TransactionDefinition definition = new DefaultTransactionDefinition();
        
        // 开始事务
        TransactionStatus status = transactionManager.getTransaction(definition);

        try {
            // 执行业务逻辑
            // ...

            transactionManager.commit(status); // 事务提交
        } catch (Exception e) {
            transactionManager.rollback(status); // 事务回滚
        }
    }
}

在这个例子中,小黑使用PlatformTransactionManager来明确开始和结束一个事务。这种方式虽然比传统的JDBC事务管理更为抽象,但仍然需要手动控制事务的边界。

事务定义和传播

在Spring中,事务是通过TransactionDefinition接口定义的。这个接口包含了各种与事务相关的属性,如隔离级别、超时时间、只读状态等。这些属性允许咱们根据具体需求定制事务的行为。

举个例子,如果小黑想要创建一个新的、独立于当前事务的事务,可以这样做:

import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionDefinition;

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

在这段代码中,PROPAGATION_REQUIRES_NEW 表示如果当前存在事务,则挂起当前事务,并创建一个全新的事务。这种灵活性是Spring事务管理非常强大的一个方面。

事务状态和回滚

除了定义事务,Spring还提供了TransactionStatus接口来跟踪事务的当前状态。这个接口让咱们可以在运行时检查事务是否已经完成,是否有回滚等。

在事务过程中,如果发生了异常,Spring允许咱们明确指定哪些异常应该触发事务回滚。这是通过@Transactional 注解的rollbackFor 属性实现的:

import org.springframework.transaction.annotation.Transactional;

@Transactional(rollbackFor = Exception.class)
public void someTransactionalMethod() {
    // ...
}

在这个例子中,任何Exception类型的异常都会触发事务回滚。这种灵活的异常处理机制使得事务管理更加健壮和可靠。

第4章:声明式事务管理

现在小黑带大家深入了解Spring的声明式事务管理。在Spring中,声明式事务管理是通过@Transactional注解来实现的。这种方法的好处是极大地简化了代码,让事务管理变得更加直观和容易维护。

使用@Transactional注解

@Transactional注解可以应用于类或者方法上。当应用于类时,该类中的所有公共方法都会被视为事务方法。而当应用于方法时,只有标注了该注解的方法才会被视为事务方法。

来看一个简单的例子:

import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;

@Service
public class AccountService {

    @Transactional
    public void transferFunds(String fromAccountId, String toAccountId, Double amount) {
        // 这里是转账的业务逻辑
        // 包括从一个账户扣钱和向另一个账户加钱
        // 如果在这个过程中发生任何异常,事务将自动回滚
    }
}

在这个例子中,transferFunds 方法上的@Transactional注解告诉Spring,这个方法需要在事务环境中运行。如果在执行过程中发生异常,Spring将自动回滚事务。

事务的传播行为

事务的传播行为定义了事务方法之间相互调用时的行为。Spring提供了多种传播行为选项,例如PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEW等。这些选项可以根据业务需求进行选择。

例如,小黑想要创建一个新的事务,而不管当前是否存在事务,可以这样设置:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void someMethod() {
    // ...
}
只读事务

如果事务仅涉及到数据读取,没有数据的修改,小黑可以将事务标记为只读。这可以优化事务的执行,特别是在使用某些类型的事务管理器(如Hibernate事务管理器)时。

例如:

@Transactional(readOnly = true)
public List<Account> findAllAccounts() {
    // ...
}
事务的隔离级别

事务的隔离级别决定了一个事务可能受其他并发事务影响的程度。Spring提供了与J

DBC相同的隔离级别,例如ISOLATION_READ_COMMITTEDISOLATION_SERIALIZABLE等。小黑可以根据具体的数据一致性和并发要求选择合适的隔离级别。

比如,如果小黑希望在事务中防止脏读,可以设置隔离级别为 READ_COMMITTED

@Transactional(isolation = Isolation.READ_COMMITTED)
public void someSensitiveOperation() {
    // 这里的操作会避免脏读的发生
}
异常回滚策略

在声明式事务管理中,Spring默认只在运行时异常和错误发生时回滚事务。但是,小黑可以自定义回滚规则,指定特定的异常类型来触发事务回滚。

例如,如果小黑想要在特定的检查型异常发生时也回滚事务,可以这样设置:

@Transactional(rollbackFor = {CustomCheckedException.class})
public void someOperation() throws CustomCheckedException {
    // ...
}

通过这些设置,咱们可以非常灵活地控制事务的行为,以满足不同的业务需求。声明式事务管理不仅使得事务的使用变得简单,而且提高了代码的清晰度和可维护性。

第5章:编程式事务管理

何时使用编程式事务管理

编程式事务管理是在代码中显式地控制事务的开始、提交和回滚。这种方式在需要对事务进行细粒度控制的场景下非常有用。比如,当事务操作需要根据运行时的某些条件动态决定,或者在一个大的事务中需要处理多个独立的小事务时。

使用TransactionTemplate

Spring为编程式事务管理提供了一个方便的类:TransactionTemplate。这个类简化了编程式事务管理,让咱们能够更加方便地实现事务逻辑。

来看看TransactionTemplate的基本用法:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

public class ProgrammaticallyTransaction {

    private final TransactionTemplate transactionTemplate;

    public ProgrammaticallyTransaction(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public Object someBusinessLogic() {
        return transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 这里写入事务的业务逻辑
                // 可以根据需要调用status.setRollbackOnly()来回滚事务
                return null;
                // 返回值可以是业务逻辑的结果
            }
        });
    }
}

在这个例子中,咱们使用TransactionTemplate来定义一个事务块。execute方法接受一个TransactionCallback,其中包含了要在事务中执行的业务逻辑。如果在执行过程中没有异常抛出,事务将自动提交;如果有异常抛出或显式调用status.setRollbackOnly(),事务将回滚。

使用PlatformTransactionManager

对于想要更深层次控制事务的小黑,可以直接使用PlatformTransactionManager。这种方法

提供了对事务操作最完全的控制,但也意味着需要更多的代码和复杂性。

让我们来看一个使用PlatformTransactionManager的例子:

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class ManualTransaction {

    private final PlatformTransactionManager transactionManager;

    public ManualTransaction(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void executeBusinessLogic() {
        TransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(definition);

        try {
            // 这里进行具体的业务操作
            // ...

            transactionManager.commit(status); // 业务成功,提交事务
        } catch (Exception e) {
            transactionManager.rollback(status); // 出现异常,回滚事务
            throw e;
        }
    }
}

在这段代码中,咱们首先创建了一个TransactionDefinition对象来定义事务的属性,然后通过transactionManager.getTransaction(definition)开始一个新的事务,并获取一个TransactionStatus对象。这个对象可以用来在事务执行过程中检查事务的状态,以及在需要时回滚事务。如果业务逻辑顺利完成,就调用transactionManager.commit(status)来提交事务;如果捕获到异常,则调用transactionManager.rollback(status)来回滚事务。

编程式事务管理虽然提供了更多的灵活性和控制力,但也带来了更多的复杂性。咱们在选择使用哪种事务管理策略时,需要考虑到业务逻辑的复杂性和对事务控制的需求。

声明式事务管理对于大多数情况下已经足够好用,但当需要特定的事务控制逻辑时,编程式事务管理就显得尤为重要了。

编程式事务管理让咱们能够精确控制事务的每个细节,这在处理复杂的业务逻辑或者需要根据不同情况灵活处理事务时非常有用。例如,在一个复杂的数据处理过程中,可能只有部分步骤需要事务控制,或者需要根据某些条件动态决定是否回滚事务。在这些情况下,编程式事务管理提供了必要的灵活性和精确控制。

第6章:Spring事务管理的高级特性

事务的传播行为

在Spring中,事务的传播行为定义了一个事务方法是如何关联到现有事务的。这对于理解和设计复杂的事务逻辑非常关键。

  • PROPAGATION_REQUIRED:如果当前有事务,就加入该事务;如果没有,就新建一个事务。
  • PROPAGATION_REQUIRES_NEW:总是创建一个新的事务,如果有现有事务,将其挂起。
  • PROPAGATION_SUPPORTS:如果当前有事务,就加入事务,没有则非事务方式执行。
  • ……更多行为如PROPAGATION_MANDATORYPROPAGATION_NEVER等。

来看个例子:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void someMethod() {
    // 这个方法总是在新的事务中运行
}
事务的隔离级别

事务的隔离级别决定了一个事务对于其他并发事务的可见性。不同的隔离级别可以防止诸如脏读、不可重复读、幻读等问题。

  • ISOLATION_READ_UNCOMMITTED:允许读取尚未提交的数据变更,可能会导致脏读、不可重复读和幻读。
  • ISOLATION_READ_COMMITTED:允许在一个事务中读取另一个已经提交的事务所做的更改。
  • ISOLATION_REPEATABLE_READ:确保如果在事务中一次读取了数据,则可以多次重复读取同样的数据。
  • ISOLATION_SERIALIZABLE:完全遵守ACID的原则,确保不发生脏读、不可重复读和幻读。

例如:

@Transactional(isolation = Isolation.SERIALIZABLE)
public void performHighlySensitiveOperation() {
    // 这里的操作将会在最严格的隔离级别下执行
}
只读事务和超时设置
  • 只读事务:如果事务只是读取

数据而不做任何更新,小黑可以将事务标记为只读。这样做可以帮助数据库优化事务,提高性能。

@Transactional(readOnly = true)
public List<User> getUsers() {
    // 这个事务只读取数据,不做修改
}
  • 超时设置:在Spring中,可以为事务指定一个超时时间。如果事务超出了这个时间范围,它会被自动回滚。这对于避免长时间占用资源非常有用。
@Transactional(timeout = 10) //

10秒超时
public void processLargeData() {
    // 这个事务处理大量数据,但如果超过10秒还没完成,就会自动回滚
}

通过设置只读事务和超时时间,咱们可以进一步优化事务的性能和稳定性,特别是在处理大量数据或者复杂查询时。

事务同步和异常处理

在Spring事务管理中,事务同步是指事务的状态与正在执行的业务逻辑之间的协调。Spring通过TransactionSynchronizationManager来管理事务同步,确保资源(如数据库连接)在事务开始时打开,在事务结束时正确关闭。

异常处理也是事务管理中的重要部分。默认情况下,Spring只在运行时异常发生时回滚事务。但咱们可以通过@Transactional注解的rollbackFor属性来自定义哪些异常应该触发回滚。

例如:

@Transactional(rollbackFor = {CustomException.class})
public void serviceMethod() {
    // 这个方法在抛出CustomException时会触发事务回滚
}

通过理解和运用这些高级特性,咱们可以在Spring中实现复杂且健壮的事务管理策略。这些功能使得Spring事务管理非常强大,满足了各种复杂业务场景的需求。

第7章:事务同步和异常处理

事务同步

在Spring中,事务同步主要是指在事务过程中保持数据源、缓存、消息等资源的一致状态。这是通过TransactionSynchronizationManager来实现的,它是Spring事务管理的核心组件之一。

TransactionSynchronizationManager可以注册事务同步回调,以便在事务的不同阶段执行特定的操作。例如,可以在事务提交或回滚时清除缓存,或者更新某些与事务状态相关的数据。

来看个示例:

import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public void registerSynchronization() {
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
        @Override
        public void afterCommit() {
            // 事务提交后执行的操作
            // 例如,清除某些缓存
        }

        @Override
        public void afterCompletion(int status) {
            // 事务完成后执行的操作(无论是提交还是回滚)
            // 例如,发送通知或更新状态
        }
    });
}
异常处理

在Spring的事务管理中,正确处理异常是保证事务正确回滚的关键。Spring默认在遇到运行时异常和错误时回滚事务。对于检查型异常,默认情况下不会触发回滚。

咱们可以通过在@Transactional注解中指定rollbackFornoRollbackFor属性来定制哪些异常应该触发事务回滚,哪些不应该。

例如,小黑想在特定的检查型异常发生时回滚事务:

import org.springframework.transaction.annotation.Transactional;

@Transactional(rollbackFor = {MyCheckedException.class})
public void myTransactionalMethod() throws MyCheckedException {
    // 这里的代码在抛出MyCheckedException异常时会触发事务回滚
}

反之,如果小黑想要在特定的运行时异常发生时不回滚事务,可以这样设置:

@Transactional(noRollbackFor = {MyRuntimeException.class})
public void anotherTransactionalMethod() {
    // 这里的代码在抛出MyRuntimeException时不会触

发事务回滚
}

正确的异常处理策略对于维持数据库的一致性和避免不必要的数据损失至关重要。咱们在设计事务管理逻辑时,需要仔细考虑哪些操作可能会抛出异常,以及这些异常应如何影响事务的行为。

事务同步不仅帮助管理事务内部的资源,还能够确保事务的外部效应(如缓存更新、消息发送等)与事务状态保持一致。而灵活而强大的异常处理机制则允许咱们精确控制事务的回滚行为,从而更好地应对复杂的业务场景。掌握了这些知识,咱们就能更加自信地管理和优化自己的Spring应用了。

第8章:最佳实践和常见问题

最佳实践
  1. 明智地选择事务边界:确保事务不会太大或太小。过大的事务可能会锁定太多资源,影响性能;过小的事务则可能无法有效保护数据的完整性。

  2. 合理使用声明式和编程式事务管理:尽管声明式事务管理更简洁,但在需要更细致控制的场景下,编程式事务管理可能更合适。

  3. 避免事务中的远程调用:在事务中进行远程调用(如HTTP请求、远程方法调用)会增加事务持续时间,增加数据库锁定时间,影响系统性能。

  4. 不要在事务中处理太多的业务逻辑:尽量保持事务简洁,聚焦于数据访问操作,以减少事务执行时间。

  5. 仔细选择事务的隔离级别:不同的隔离级别有不同的性能影响。选择恰当的隔离级别可以避免不必要的性能开销。

常见问题及解决方案
  1. 问题:事务不回滚
    解决方案:检查是否正确使用了@Transactional注解,以及是否在适当的异常上触发了回滚。

  2. 问题:事务管理器没有正确配置

    解决方案:确保Spring配置中正确声明了事务管理器,并且所有事务相关的操作都在其管理范围内。

  3. 问题:不恰当的事务传播行为导致的问题
    解决方案:理解不同事务传播行为的含义,根据具体的业务场景选择合适的传播行为。

  4. 问题:脏读、不可重复读和幻读
    解决方案:通过设置合适的事务隔离级别来避免这些问题。例如,ISOLATION_REPEATABLE_READ可以防止不可重复读,ISOLATION_SERIALIZABLE可以防止幻读。

  5. 问题:长事务影响系统性能
    解决方案:重新审视业务逻辑,将长事务拆分成多个短事务,或将非关键操作移出事务。

示例:选择正确的事务传播行为

在使用Spring事务时,正确选择事务传播行为是非常关键的。例如,假设有一个服务类需要在已有事务中执行,可以使用PROPAGATION_REQUIRED

import org.springframework.transaction.annotation.Transactional;

@Transactional(propagation = Propagation.REQUIRED)
public class MyService {
    public void performService() {
        // 业务逻辑
    }
}

如果这个方法需要在自己的独立事务中执行,而不管外部是否存在事务,可以使用PROPAGATION_REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)
public class MyService {
    public void performIndependentService() {
        // 独立的业务逻辑
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV——多分辨率LBP的计算方法

目录 一、算法原理1、原理概述2、参考文献 二、代码实现三、结果展示 OpenCV——多分辨率LBP的计算方法由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、算法原理 1、原理概述 基本LBP算子虽然在早期…

Qt/QML编程学习之心得:使用camera摄像头(35)

汽车应用中,camera起到了越来越多的作用,数字化的作用,这点无可争议,而作为GUI设计工具,如何让Camera类的应用能更好的发挥作用呢? You can use Camera to capture images and movies from a camera, and manipulate the capture and processing settings that get appl…

关于 setData 同步异步的问题

小程序官方文档中的回答解释: 所以大概意思就是: 1.setData在逻辑层的操作是同步&#xff0c;因此this.data中的相关数据会立即更新,比如下面的例子: const a 1 this.setData({b: a ? a : , }) console.log(that.data.b) // 1 2. setData在视图层的操作是异步&#xff0c;…

Linux Ubuntu搭建我的世界Minecraft服务器实现好友远程联机MC游戏

文章目录 前言1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 前言 Li…

C语言之从浅入深一步一步全方位理解指针【附笔试题】

文章目录 前言从浅入深理解指针《第一阶段》一、内存和地址1.1 内存1.2 究竟该如何理解编址 二、指针变量和地址2.1 取地址操作符&#xff08;&&#xff09; 三、指针变量和解引用操作符&#xff08;*&#xff09;3.1 指针变量3.2 如何拆解指针类型3.3 解引用操作符 四、指…

web网页设计学习记录(五)

1.如何设置背景色呢&#xff1f; 格式为&#xff1a; <body bgcolor"色彩值"> “色彩值”可以为色彩的英文名或相应十六进制值。 2.如何将图片作为背景呢&#xff1f; 格式为&#xff1a;<body background"图片文件名"> 使用<body&g…

具于xilinx FPGA的可动态配置DDS频率控制字的DDS IP核使用例程详解

目录 1 概述2 IP examples功能3 IP 使用例程4注意事项5 DDS IP Examples下载位置 1 概述 本文用于讲解xilinx IP 的dds ip examples&#xff08;动态配置频率&#xff09;的功能说明&#xff0c;方便使用者快速上手。 2 IP examples功能 本examples 是月隐编写的针对DDS的使…

一分钟找到所有的中文核心期刊

1.进入中国知网找到出版物检索 2.在出版来源导航这里选择期刊导航 3.右边拉到底选择核心期刊导航 4.选择自己专业的期刊即可

软件设计不是CRUD(10):低耦合模块设计理论——业务抽象:从需求中提取业务维度

接上文《软件设计不是CRUD(9):低耦合模块设计理论——设计落地所面临的挑战》 2、什么是业务抽象 业务抽象是一种将需求落地成模块功能的设计思想,是对业务需求和技术设计进行转换、隔离的一种分析方法。经过业务抽象后的业务模块一般具有较高的业务屈服度,能更大程度满…

Hex Editor的使用教程(VS Code)

Hex Editor&#xff08;十六进制编辑器&#xff09;是一种用于查看和编辑计算机文件的低级别编辑工具。与常规文本编辑器不同&#xff0c;它允许用户直接查看和修改文件的二进制数据。在 Hex Editor 中&#xff0c;数据通常以十六进制&#xff08;hex&#xff09;格式显示&…

Arduino| IDE下载、安装和设置以及开发板的连接

IDE下载、安装和设置以及开发板的连接 IDE下载IDE安装IDE设置首选项——设置语言、字体、主题、地址等等开发板管理器——添加开发板 开发板的连接 IDE下载 第一步&#xff1a;进入Arduino官网https://www.arduino.cc。 第二步&#xff1a;选择导航栏的Software&#xff0c;然…

【论文阅读笔记】Prompt Tuning for Parameter-efficient Medical Image Segmentation

Fischer M, Bartler A, Yang B. Prompt tuning for parameter-efficient medical image segmentation[J]. Medical Image Analysis, 2024, 91: 103024. 【开源】 【核心思想】 本文的核心思想是提出了一种用于医学图像分割的参数高效的提示调整&#xff08;Prompt Tuning&…

Flutter开发进阶之动画

Flutter开发进阶之动画 在Flutter中&#xff0c;动画是至关重要的一个部分&#xff0c;它能够为应用程序提供更加丰富和生动的用户体验&#xff0c;Flutter中的动画系统是UI框架的核心功能之一&#xff0c;也是开发者学习Flutter框架的重要部分&#xff0c;由于动画原理在所有…

实时时钟芯片DS1302单片机C语言驱动程序

实时时钟RTC相关索引 1.单片机RTC及时钟芯片的时间到底从哪一年起始&#xff1f; 2.STM32F103单片机内部RTC实时时钟驱动程序 3.实时时钟芯片DS1302单片机C语言驱动程序 一、DS1302简介 DS1302 是 DALLAS&#xff08;达拉斯&#xff09;公司推出的一款涓流充电时钟芯片。 主…

Aigtek超声功率放大器的选型技巧及参数指标有哪些

超声功率放大器是一种广泛应用于声学测量、医疗成像、声纳等领域的装置&#xff0c;其作用是将输入信号的功率放大到需要的水平。在选型超声功率放大器时&#xff0c;需要考虑一些关键的技巧和参数指标&#xff0c;以确保选择合适的设备来满足特定的需求。 首先&#xff0c;需要…

【java八股文】之Spring系列篇

1、你怎么理解Spring&#xff1f; Spring是个轻量级的框架&#xff0c;简化了应用的开发程序&#xff0c;提高开发人员的系统维护性&#xff0c;不过配置消息比较繁琐&#xff0c;所以后面才出选了SpringBoot的框架。 Spring的核心组件 &#xff1a; Spring Core 、 Spring Con…

【Python数据可视化】matplotlib之设置子图:绘制子图、子图共享x轴坐标

文章传送门 Python 数据可视化matplotlib之绘制常用图形&#xff1a;折线图、柱状图&#xff08;条形图&#xff09;、饼图和直方图matplotlib之设置坐标&#xff1a;添加坐标轴名字、设置坐标范围、设置主次刻度、坐标轴文字旋转并标出坐标值matplotlib之增加图形内容&#x…

CDSP和CISP证书,选择哪个?

&#x1f3af;CDSP和CISP是两种与信息安全领域相关的专业认证。它们有一些相似之处&#xff0c;但也存在一些显著的区别。本文将详细介绍CDSP认证和CISP认证的相同点和区别。 &#x1f451;CDSP和CISP的相同点&#xff1a; 1.行业认可&#xff1a;CDSP和CISP都是行业广泛认可的…

机器视觉系统选型-参数—景深

镜头在垂直方向上&#xff0c;能清晰成像的空间距离(清晰成像范围)&#xff0c;称为景深

强化学习应用(八):基于Q-learning算法的无人车配送路径规划(通过Python代码)

一、Q-learning算法介绍 Q-learning是一种强化学习算法&#xff0c;用于解决基于环境的决策问题。它通过学习一个Q-table来指导智能体在不同状态下采取最优动作。下面是Q-learning算法的基本步骤&#xff1a; 1. 定义环境&#xff1a;确定问题的状态和动作空间&#xff0c;并…
最新文章