Spring 面试题, Spring 事务在什么情况下会失效?
Spring 面试题, Spring 事务在什么情况下会失效?
QA
Step 1
Q:: Spring 事务在什么情况下会失效?
A:: Spring 事务可能会在以下几种情况下失效:
1.
非公共方法调用:只有 public
方法才会被 Spring 的事务管理器代理,内部调用的 private
、protected
方法不会触发事务。
2.
同一类内部方法调用:当同一个类中方法调用时,如果调用者和被调用者都属于同一个类,则事务不会被应用。因为 Spring 的事务机制是通过代理实现的,内部调用不会经过代理。
3.
未被 Spring 管理的 Bean:如果事务注解所在的类没有被 Spring 管理(例如没有使用 @Component
注解或手动实例化对象),事务将不会生效。
4.
非运行时异常:默认情况下,Spring 事务只会在抛出 RuntimeException
时回滚。如果抛出的是检查异常(checked exception
),事务不会回滚,除非使用 rollbackFor
属性指定。
5.
多线程环境:在多线程环境下,Spring 的事务管理器可能无法正确地处理事务,因为每个线程都有自己独立的事务上下文。
6.
事务传播行为设置不当:如果在某些情况下,事务传播行为设置不正确(例如使用 REQUIRES_NEW
而不是 REQUIRED
),可能会导致事务失效。
Step 2
Q:: Spring 如何保证事务的原子性、一致性、隔离性和持久性(ACID)?
A:: Spring 通过以下方式保证事务的ACID特性:
1. **原子性**:通过事务的边界(begin 和 commit/
rollback)来保证操作的原子性,所有的操作要么全部成功,要么全部回滚。
2.
一致性:通过事务提交或回滚时的状态保持,保证数据库从一个一致性状态转换到另一个一致性状态。
3.
隔离性:Spring 允许通过 @Transactional
注解中的 isolation
属性设置不同的隔离级别(如 READ_COMMITTED
,REPEATABLE_READ
,SERIALIZABLE
),以控制事务之间的相互影响。
4.
持久性:Spring 依赖于底层数据库的持久性保证,确保事务提交后的数据即使在系统崩溃的情况下也能持久保存。
Step 3
Q:: Spring 中事务的传播行为有哪些?
A:: Spring 事务的传播行为定义了事务方法被调用时事务的处理方式。常见的传播行为包括:
1.
REQUIRED:默认值,方法运行在一个现有事务中,如果没有事务,则创建一个新事务。
2.
REQUIRES_NEW:总是创建一个新的事务,当前事务(如果存在)将被挂起。
3.
SUPPORTS:方法可以在有事务的情况下运行,如果当前没有事务,也可以不使用事务。
4.
NOT_SUPPORTED:方法不应该在事务中运行,如果当前有事务,则该事务将被挂起。
5.
MANDATORY:方法必须在现有事务中运行,如果没有事务,则抛出异常。
6.
NEVER:方法不应该在事务中运行,如果当前有事务,则抛出异常。
7.
NESTED:如果当前存在事务,则方法将运行在一个嵌套事务中,嵌套事务可以独立于外部事务提交或回滚。
Step 4
Q:: 如何在 Spring 中自定义事务管理器?
A:: 在 Spring 中可以通过以下方式自定义事务管理器:
1.
配置多个事务管理器:可以通过在配置类或 XML 中定义多个 PlatformTransactionManager
bean,并使用 @Primary
注解指定默认的事务管理器。
2.
事务管理器注入:可以将自定义的事务管理器注入到使用 @Transactional
的服务类中,或者直接在 @Transactional
注解中指定特定的事务管理器。
3.
扩展 AbstractPlatformTransactionManager
类:可以通过继承 Spring 的 AbstractPlatformTransactionManager
类来实现自定义的事务管理逻辑。