知识卡片
声明式事务标注的放置陷阱
内容
声明式事务标注(如@Transactional)之所以能生效,是因为框架在背后生成了一个代理对象 包裹目标类,方法调用先经过代理、由代理负责开启和提交事务,再转发给真正的实现。这意味着 标注必须放在代理机制能够拦截到的地方:方法必须是public的,因为大多数基于代理的实现无法 拦截非public方法的调用;标注也不该只放在接口上(当使用生成子类的动态代理时),因为代理 拦截的是具体类的方法调用,接口上的标注可能不会被识别。一旦事务”看起来配置了却没生效”, 第一反应应该是检查方法可见性和标注位置,而不是怀疑事务框架本身坏了。发散:这是所有基于 代理/拦截器实现的横切关注点(事务、缓存、权限校验)共有的陷阱——凡是”标注了却没生效” 的诡异问题,十有八九是标注放的位置代理机制根本拦不到,而不是标注语法写错了。
参考来源
《精通Hibernate》附录D《使用Spring Framework的事务标注》