Spring @Cacheable注解 && 事务@Transactional 在同一个类中的方法调用不生效
@Cacheable 注解在对象内部调用不会生效
代码示例:
ProductServiceImpl.java
public List<ProductInfoVO> getProductList(CommonRequest<ProductInfoDTO> reqest) {
// @Cacheable失效,不会走缓存的
return this.findProductInfoList(reqest);
}
@Cacheable(cacheNames = "productInfos",cacheManager="jfinetchRedisCacheManager", key = "'jbs:product:list:'.concat(#reqest.getChannelCode())")
public List<ProductInfoVO> findProductInfoList(CommonRequest<ProductInfoDTO> reqest){
List<ProductInfoVO> redisList = productService.findList(reqest);
redisList = redisList.stream().filter(it -> ProductStatusEnum.OPEN.getCode().equals(it.getStatus())).collect(Collectors.toList());
return redisList;
}
此时getProductList 调用findProductInfoList缓存注解@Cacheable 是不会生效的。
原因:
Spring 缓存注解是基于Spring AOP切面,必须走代理才能生效,同类调用或者子类调用父类带有缓存注解的方法时属于内部调用,没有走代理,所以注解不生效。
spring的@Transactional事务生效的一个前提是进行方法调用前经过拦截器TransactionInterceptor,也就是说只有通过TransactionInterceptor拦截器的方法才会被加入到spring事务管理中,查看spring源码可以看到,在AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice方法中会从调用方法中获取@Transactional注解,如果有该注解,则启用事务,否则不启用。
这个方法是通过spring的AOP类CglibAopProxy的内部类DynamicAdvisedInterceptor调用的,而DynamicAdvisedInterceptor继承了MethodInterceptor,用于拦截方法调用,并从中获取调用链。
这个方法是通过spring的AOP类CglibAopProxy的内部类DynamicAdvisedInterceptor调用的,而DynamicAdvisedInterceptor继承了MethodInterceptor,用于拦截方法调用,并从中获取调用链。
Transactional是Spring提供的事务管理注解。
重点在于,Spring采用动态代理(AOP)实现对bean的管理和切片,它为我们的每个class生成一个代理对象。只有在代理对象之间进行调用时,可以触发切面逻辑。
而在同一个class中,方法B调用方法A,调用的是原对象的方法,而不通过代理对象。所以Spring无法切到这次调用,也就无法通过注解保证事务性了。
也就是说,在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用。
解决方法
1.可以把removeGroupUserStatusCached方法单独抽取到另外一个类里面,通过代理类引入。
2.通过((GroupUserService)AopContext.currentProxy()).removeGroupUserStatusCached方法获取当前类的代理类;
3.通过ApplicationContext获取当前类的代理对象,GroupUserService groupUserService = springContextUtil.getBean(GroupUserService.class);
可以将方法放入另一个类,并且该类通过spring注入,即符合了在对象之间调用的条件。
获取本对象的代理对象,再进行调用。具体操作如:
Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy=“true”/>
在xxxServiceImpl中,用(xxxService)(AopContext.currentProxy()),获取到xxxService的代理类,再调用事务方法,强行经过代理类,激活事务切面。
Spring @Cacheable注解 && 事务@Transactional 在同一个类中的方法调用不生效的更多相关文章
- 梳理:python—同一个类中的方法调用
为什么突然在此提到这个梳理问题呢? 因为在自己实践综合练习学过的知识时,突然觉得有些知识点的运用总是不成功,于是翻过课本进行回顾,总是觉得是对的,可是当再进一步思考“既然是对的,为什么在程序中总是不成 ...
- 分析spring事务@Transactional注解在同一个类中的方法之间调用不生效的原因及解决方案
问题: 在Spring管理的项目中,方法A使用了Transactional注解,试图实现事务性.但当同一个class中的方法B调用方法A时,会发现方法A中的异常不再导致回滚,也即事务失效了. 当这个方 ...
- Spring事务:调用同一个类中的方法
问题: 如果同一个类中有方法:methodA(); methodB().methodA()没有开启事务,methodB()开启了事务 且methodA()会调用methodB(). 那么,method ...
- java中方法内可以调用同一个类中的方法
在同一个类中,java的普通方法的相互调用,可以使用this+点号+方法名,也可省略this+点号,java编 译器会自动补上.
- Spring 之注解事务 @Transactional
众所周知的ACID属性: 原子性(atomicity).一致性(consistency).隔离性(isolation)以及持久性(durability).我们无法控制一致性.原子性以及持久性,但可以 ...
- 【@Transactional】Spring 之注解事务 @Transactional
spring 事务注解 默认遇到throw new RuntimeException("...");会回滚 需要捕获的throw new Exception("...&q ...
- Spring 之注解事务 @Transactional(转载)
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播: 事务传播行为类型 事务传播行为类型 说明 P ...
- spring 事务处理中,同一个类中:A方法(无事务)调B方法(有事务),事务不生效问题
public class MyEntry implements IBaseService{ public String A(String jsonStr) throws Exception{ User ...
- Transaction 在同一个类中不生效
参考:https://blog.csdn.net/qq_30336433/article/details/83338835 最近在开发项目中踩到一个坑,以此记录下来.以备后来人借鉴 1.相信使用spr ...
随机推荐
- c# 通过win32 api 得到指定Console application Content
已知的问题: 1. 调试的时候会报IO 异常,非调试环境是正常的 2. Windows 应用程序才可以使用,可以用非windows应用程序包一层 using System; using System. ...
- Python正则简单实例分析
Python正则简单实例分析 本文实例讲述了Python正则简单用法.分享给大家供大家参考,具体如下: 悄悄打入公司内部UED的一个Python爱好者小众群,前两天一位牛人发了条消息: 小的测试题: ...
- Flask自动刷新前端页面(方便调试)livereload
是不是每次调整模板文件,就要停止flask服务器,重启flask服务器,再去浏览器刷新页面? 有没有办法自动完成这3步呢? 安装livereload即可, 仅仅把app.run() 改为下面的例子就可 ...
- iOS——学习网址收集
1 一个比系统自带的终端好用的软件:http://www.iterm2.com 2 学习和遇到技术问题可以去的网站: CocoaChina http://developer.cocoachi ...
- [Linux]虚拟机下安装ubuntu后root密码设置
转自:https://blog.csdn.net/zcyhappy1314/article/details/17448223 问题描述: 在虚拟机下安装了ubuntu中要输入用户名,一般情况下大家都会 ...
- mysql语句笔记
创建数据库 create database name(自定义): #创建一个数据库 name自己取 create database if not exists name() default cha ...
- POJ 2386 DFS深搜入门
题目链接 Time Limit: 1000MS Memory Limit: 65536K Description Due to recent rains, water has pooled in va ...
- 错误: 找不到或无法加载主类 java操作hbase出错
用java操作hbase 利用maven引入hbase包后发现无法启动程序,然后网上说是包的冲突. 我引入了下面三个包然后程序就不能运行了. <dependency> <groupI ...
- Openresty 健康检查
## 指定共享内存 lua_shared_dict healthcheck 1m; ## 在worker初始化过程中,启动定时器,进行后端结点的检查 init_worker_by_lua_block ...
- HashMap、HashTable与ConcurrentHashMap的区别
1.HashTable与HashMap (1)HashTable和HashMap都实现了Map接口,但是HashTable的实现是基于Dictionary抽象类. (2)在HashMap中,null可 ...