Spring注解(如@Transactional、@Cacheable、@Async等),在使用不当时,很可能会失效。失效的情况有很多种,本文我们就来瞅瞅,为啥同一个类中普通方法调用Spring注解方法,注解会失效呢?

有一些同学可能不知道其中原由,别急,让我来为大家揭晓答案。

听说你很懂源码?Spring读懂了?还有这20道源码面试题接得住吗?​zhuanlan.zhihu.com

Spring在扫描bean的时候,如果扫描到方法上有这些注解,那么spring会通过动态代理模式,为这个bean动态地生成一个代理类,在代理类中,会对有注解的这个方法,做一些增强处理,如给有@Transactional注解的方法开启transaction。

当我们想要调用这个方法时,实际上是先调用了代理对象中被增强的方法,然后在代理对象中,又会调用我们实际的目标对象中的方法。在通过代理对象中转的这一过程中,像上边说的开启和提交transaction就实现了。

实现机制我们大体知道了,下面我们用代码来模拟演示一下。

假设我们订单业务处理类中,有两个方法:校验订单参数方法verifyOrderParameters() 和 保存订单方法saveOrder(),其中saveOrder方法上加了@Transactional注解,verifyOrderParameters方法内会调用saveOrder方法。

OrderService

/*** 订单业务层的接口定义*/
public interface OrderService {/*** 校验订单参数*/void verifyOrderParameters();/*** 保存订单*/void saveOrder();
}

OrderServiceImpl

/*** 订单业务层的具体处理类*/
public class OrderServiceImpl implements OrderService{@Overridepublic void verifyOrderParameters() {System.out.println("校验订单参数");// 调用保存订单方法saveOrder();}@Override@Transactionalpublic void saveOrder() {System.out.println("保存订单信息到DB");}
}

我们用伪代码来演示一下Spring动态代理生成的代理类。

OrderServiceImplProxy

/*** 订单业务层具体处理类的代理类*/
public class OrderServiceImplProxy implements OrderService{/*** 持有被代理的具体的目标对象*/private OrderServiceImpl orderServiceImpl;public OrderServiceImplProxy(OrderServiceImpl orderServiceImpl) {this.orderServiceImpl = orderServiceImpl;}@Overridepublic void verifyOrderParameters() {orderServiceImpl.verifyOrderParameters();}@Overridepublic void saveOrder() {System.out.println("开启事务。。。");orderServiceImpl.saveOrder();System.out.println("提交事务。。。");}
}

边我们来看下客户端调用saveOrder方法和verifyOrderParameters方法,输出结果都是什么样的。

public class Client {public static void main(String[] args) {// 创建一个订单业务的真实处理对象OrderServiceImpl orderServiceImpl = new OrderServiceImpl();// 创建一个代理对象OrderServiceImplProxy orderServiceImplProxy = new OrderServiceImplProxy(orderServiceImpl);// 执行代理对象的校验订单方法orderServiceImplProxy.verifyOrderParameters();System.out.println("--------------------------------------------");// 执行代理对象的保存订单方法orderServiceImplProxy.saveOrder();}
}

执行main方法后,得到下边的输出:

校验订单参数
保存订单信息到DB
--------------------------------------------
开启事务。。。
保存订单信息到DB
提交事务。。。

通过这个演示代码,想必同学们已经了解了吧,普通方法verifyOrderParameters内调用注解方法saveOrder时,其实调用的是原目标对象(orderServiceImpl)的saveOrder方法,没有走代理对象(orderServiceImplProxy)中被增强的saveOrder方法,所以就不会产生效果啦。

动态代理是实现Spring AOP的一个重要手段,所以大家以后再用注解以及切面时,一定要注意这个坑噢。

作者:晓呆同学
原文链接:https://blog.csdn.net/daidaineteasy/article/details/105981724

@transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...相关推荐

  1. 后端技术:Java中Spring 和 Spring Boot 有哪些区别,看完你就明白了!

    概述 对于 Spring和 SpringBoot到底有什么区别,我听到了很多答案,刚开始迈入学习 SpringBoot的我当时也是一头雾水,随着经验的积累.我慢慢理解了这两个框架到底有什么区别,相信对 ...

  2. SpringCache @Cacheable 在同一个类中调用方法,导致缓存不生效的问题及解决办法...

    由于项目需要使用SpringCache来做一点缓存,但自己之前没有使用过(其实是没有听过)SpringCache,于是,必须先学习之. 在网上找到一篇文章,比较好,就先学习了,地址是: https:/ ...

  3. spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效

    title: "spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效" url: "https://wsk1103.githu ...

  4. Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转)

    Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转) 参考文章: (1)Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转) (2)https://www. ...

  5. 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法

    在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法 参考文章: (1)在同一个类中,一个方法调用另外一个有注解(比如@Async, ...

  6. Spring同一个类中注解方法互相调用的问题

    在使用Spring时,很多初学者不了解Spring对象注入的机制和面向切面编程的原理,很容易犯一些错误.下面就是初学者最容易犯的错误.举例如下: @Component public class Tes ...

  7. Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法

    Spring 事务机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.  结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷.    ...

  8. Spring中同一个类中方法调用事务不生效,非事务方法调用事务方式事务不生效

    我们假定在SerivceXXX中有两个方法: serviceA 非事务方法 serviceB事务方法 如果serviceA中方法定义类似如下: public void serviceA(){..... ...

  9. 梳理:python—同一个类中的方法调用

    为什么突然在此提到这个梳理问题呢? 因为在自己实践综合练习学过的知识时,突然觉得有些知识点的运用总是不成功,于是翻过课本进行回顾,总是觉得是对的,可是当再进一步思考"既然是对的,为什么在程序 ...

最新文章

  1. 多项式概率分布(Multinomial probability distribution)和分类分布(categorical distribution)
  2. C++ 面向对象(类对象)
  3. python具有一些突出优点_Python具有一些突出优点,它们是:()
  4. Spring-Cloud中的统一配置中心
  5. 【算法竞赛学习】二手车交易价格预测-Task2数据分析
  6. hibernate oracle clob 注解,Hibernate3.X实现基于CLOB字段类型的注解方式:
  7. mssql如何取得两位的月份和天数
  8. Xcode4.4 import header 的问题解决方法
  9. java spring框架文件上传_spring系列---Security 安全框架使用和文件上传FastDFS
  10. InstallShield中通过修改注册表关闭Vista/Windows 7的UAC
  11. 再说“两本交换机图书内容完全不一样”
  12. 豆瓣电影Top250数据爬取、数据分析及数据可视化
  13. 手机上可以拍一寸证件照吗
  14. IT未来发展五大趋势
  15. 关于ES6中let 和 const 命令的用法以及注意事项:
  16. 微信小程序|考试系统|基于微信小程序和SpringBoot+VUE的智能在线考试系统毕业设计
  17. Unity3D 个人尝试经验总结
  18. 开源网络压测工具dperf登上了github C语言趋势榜
  19. Sweetviz:让你只需三行代码实现Python探索性数据分析
  20. shell编程-运算符-环境变量-变量类型声明

热门文章

  1. 有向图最长路径算法_算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法...
  2. 2021年12月2日星期四的 Hybris Eclipse 导入尝试
  3. 如何检测 SAP 电商云 Spartacus UI 当前正处于导航状态
  4. SAP Spartacus 如何重定义登录 Login Component
  5. SAP Spartacus 和 SmartEdit 集成的一些 bug
  6. SAP Spartacus运行时错误 - The pipe cxUrl could not be found!
  7. Chrome开发者工具Element style里的Computed标签页
  8. Angular应用一个创建场景的问题分析
  9. 浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP面向切面编程的尝试
  10. 使用SAP HANA Web-based Development Workbench进行SQLScript练习