spring声明式事务本质是基于aop代理机制,通过transactioninterceptor拦截@transactional方法,在执行前后织入事务逻辑,依赖platformtransactionmanager管理事务,并利用threadlocal实现事务上下文传递。

Spring 声明式事务本质是基于 AOP 的代理机制,在目标方法执行前后自动织入事务管理逻辑,核心是 TransactionInterceptor 与 PlatformTransactionManager 协同工作,通过动态代理拦截 @Transactional 方法调用。
代理对象的生成时机与类型选择
Spring 启动时扫描所有含 @Transactional 的 Bean,为它们创建代理。具体代理方式取决于配置和类结构:
- 如果目标类实现接口(且未强制使用 CGLIB),Spring 默认用 JDK 动态代理,生成接口的代理实例
- 如果目标类无接口、或配置了 proxy-target-class=true,则使用 CGLIB 创建子类代理
- 代理对象不是原 Bean 实例,而是包装了原始对象的代理对象,方法调用被拦截并增强
TransactionInterceptor 是事务增强的核心
@Transactional 注解本身不生效,真正起作用的是 Spring 注册的 TransactionInterceptor,它实现了 MethodInterceptor 接口:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在方法调用前,解析 @Transactional 属性(如 propagation、isolation、rollbackFor),获取或创建事务(调用 PlatformTransactionManager.getTransaction)
- 方法正常返回时,触发 commit;抛出异常时,根据 rollbackRules 判断是否回滚,再调用 commit 或 rollback
- 整个过程封装在 invoke() 方法中,由代理对象在执行目标方法时委托给它
事务上下文如何跨方法传递
事务不是靠代理“传递”的,而是依赖线程绑定的 TransactionSynchronizationManager:
- 开启事务时,将 TransactionStatus 和数据源连接(Connection)存入当前线程的 ThreadLocal
- 后续同一事务内的 DAO 操作(如 JdbcTemplate、JPA EntityManager)会自动从该 ThreadLocal 获取连接,保证操作在同一个物理事务中
- 代理只负责开启/提交/回滚事务点,而事务资源的实际复用由底层模板类(如 DataSourceUtils)配合 ThreadLocal 完成
为什么 private/protected 方法或 self-invocation 不生效
这是代理机制的天然限制,不是 Spring 的 bug:
- JDK 代理只能拦截接口方法调用;CGLIB 代理只能拦截 public 方法(final 方法也不行)
- private/protected 方法无法被代理对象访问,调用直接走原对象,绕过 TransactionInterceptor
- 类内部 this.method() 是对本对象的直接调用(非代理对象),同样跳过代理链 —— 正确做法是让容器注入自身(@Autowired 自注入)或通过 ApplicationContextHolder 获取代理对象调用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










