一、@Transactional 注解使用要点全解析
(一)方法可见性限制
@Transactional 注解在 Spring 事务管理体系中有明确的使用约束,其仅能在 public 方法上生效。这一设计决策源于 Spring 基于 AOP(面向切面编程)实现事务管理的机制。在 AOP 代理过程中,对于非 public 方法,Spring 无法通过标准的代理机制有效拦截和增强事务处理逻辑。例如,在使用基于接口的代理时,protected 或 private 方法不会被代理类覆盖,导致 @Transactional 注解无法发挥作用。即便在代码编写时没有出现语法错误,但在运行时,事务相关的功能(如自动提交、回滚)都不会按预期执行。
(二)异常回滚机制剖析
在异常处理方面,@Transactional 注解默认仅回滚非检查型异常,具体包括 RuntimeException 及其子类和 Error 子类。查看 Spring 源码中的 DefaultTransactionAttribute 类的 rollbackOn 方法,其实现逻辑清晰地展示了这一规则:
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
这意味着,如果方法中抛出了如 NullPointerException、ArrayIndexOutOfBoundsException 等 RuntimeException 或其子类异常,事务会自动回滚。而对于诸如 IOException 等检查型异常,默认情况下事务不会回滚。不过,开发者可以通过 rollbackFor 属性灵活指定回滚的异常类型,如 @Transactional(rollbackFor = Exception.class)
,这样一来,无论是检查型还是非检查型异常,只要是 Exception 类及其子类异常抛出,事务都会进行回滚操作,从而满足特定业务场景下对异常处理和事务一致性的严格要求。
(三)异常捕获与事务回滚关系
当异常在 try{}catch()块内被捕获时,@Transactional 注解无法自动回滚该异常对应的事务。这是因为一旦异常在方法内部被捕获,事务管理器就无法感知到异常的发生,进而不会触发默认的回滚机制。例如:
@Transactional
public void someMethod() {
try {
// 业务逻辑代码,可能会抛出异常
someDao.save(data);
} catch (Exception e) {
// 异常被捕获,在此处进行了处理,但事务不会自动回滚
logger.error(&#