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 ...
随机推荐
- 自定义MyBatis
自定义MyBatis是为了深入了解MyBatis的原理 主要的调用是这样的: //1.读取配置文件 InputStream in = Resources.getResourceAsStream(&qu ...
- 微信小程序tabBar底部导航 不显示问题解析
2019年十月八号 转藏: 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/wy_Blo ...
- 【NPDP笔记】第二章 组合管理
2.1 什么是产品组合 Product Portfolio 什么是组合管理,讲述的是完成正确的项目, 五大目标 财务稳健,财务目标 管道平衡,资源需求与可用资源之间的平衡 战略协同,与经营战略 组织战 ...
- MySQL5.7修改wait_timeout参数
参考:https://blog.csdn.net/ivory_town1/article/details/77702357 1.修改参数配置文件 vi /etc/my.cnf [mysqld] wai ...
- China.NETConf2019 - 用ASP.NETCore构建可检测的高可用服务
一.前言 2019 中国 .NET 开发者峰会(.NET Conf China 2019)于2019年11月10日完美谢幕,校宝在线作为星牌赞助给予了峰会大力支持,我和项斌等一行十位同事以讲师.志愿者 ...
- win7下IntelliJ IDEA使用curl
curl是利用URL语法在命令行方式下工作的开源文件传输工具 curl命令可以在开发web应用时,模拟前端发起的HTTP请求 1.下载curl https://curl.haxx.se/downloa ...
- Kubernetes 及安装注意事项
Docker Desktop for Mac/Windows开启Kubernetes 及安装注意事项 Table of Contents 1 解决方案 2 注意事项 2.1 Choose Kubeco ...
- 【记录】【MySQL】填充字符串函数 LPAD(str,len,padstr)
LPAD(str,len,padstr) 1.如果str的长度等于len,那么就返回str 2.如果str的长度大于len,那么就返回str的前len个长度 3.如果str的长度小于len,那么就返回 ...
- 解决angular+element原有组件样式不能覆盖element自带样式问题
在对应的组件中写入 ::ng-deep + 想要改变的element组件样式名即可
- 在linux上安装redis
下载Redis安装包 wget http://download.redis.io/releases/redis-3.2.9.tar.gz 解压Redis安装包 tar -zxvf redis-3.2 ...