Spring @Cacheable注解类内部调用失效的解决方案

目录
  • @Cacheable注解类内部调用失效
  • @Cacheable注解缓存方法内部调用
    • 方法一
    • 方法二
    • 方法三
    • 方法四

@Cacheable注解类内部调用失效

如果你只是想使用一个轻量级的缓存方案,那么可以尝试使用Spring cache方案。

那么在使用spring @Cacheable注解的时候,要注意,如果类A的方法f()被标注了@Cacheable注解,那么当类A的其他方法,例如:f2(),去直接调用f()的时候,@Cacheable是不起作用的,原因是@Cacheable是基于spring aop代理类,f2()属于内部方法,直接调用f()时,是不走代理的。

举个例子:

@Cacheable(key = "#entityType", value = "xxxCache")
    public List<String selectByEntityType(intentityType) {
        List<String> result = new ArrayList<>();
        //do something
        return result;
    }
public List<String> f2(){
  //Cacheable失效,不会走缓存的
  selectByEntityType(1);
}

可以把selectByEntityType方法抽取到另外的类中,例如:

@Service
public class CacheService{
@Cacheable(key = "#entityType", value = "xxxCache")
    public List<String selectByEntityType(intentityType) {
        List<String> result = new ArrayList<>();
        //do something
        return result;
    }
}

这样其他类要使用selectByEntityType方法,只能注入CacheService,走代理。

@Cacheable注解缓存方法内部调用

因为Spring Cache是基于切面的(基于AOP的动态代理实现的:即都在方法调用前后去获取方法的名称、参数、返回值,然后根据方法名称、参数生成缓存的key(自定义的key例外),进行缓存),所以内部方法调用不会调用切面,导致缓存不生效

方法一

暴露Aop代理到ThreadLocal支持,在类之前加@EnableAspectJAutoProxy(exposeProxy = true)

调用的时候使用((XxxService) AopContext.currentProxy()).method()调用方法

eg:

ApiBaseResponse<ApiPageResponse<RoadCongestIndexData>> apiPageResponseApiBaseResponse =
                ((RoadLastPageServiceImpl) AopContext.currentProxy()).queryLastPageCongestIndexData1(request);

方法二

把需要用缓存的方法单独写到一个类里面,把内部调用变成类间调用

RoadLastPageServiceImpl selfService = SpringContextUtil.getBean(RoadLastPageServiceImpl.class);
        selfService.queryLastPageCongestIndexData1(request);

方法三

类自我注入,使用@lazy和@Autowired注解实现自我注入,然后使用时用注解的实例代替this调用方法。

@Lazy
@Autowired
private RoadLastPageServiceImpl serviceImplCache;

方法四

写一个工具类,使用内部调用的时候,自己实例化一个对象,让类走AOP

@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    /**
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境
     *
     * @param applicationContext
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 获取对象
     *
     * @param name
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }
    /**
     * 通过类型获取对象
     *
     * @param t
     *            对象类型
     * @return
     * @throws BeansException
     */
    public static <T> T getBean(Class<T> t) throws BeansException {
        return applicationContext.getBean(t);
    }
}

调用的时候这么调用

RoadLastPageServiceImpl selfService = SpringContextUtil.getBean(RoadLastPageServiceImpl.class);
selfService.queryLastPageCongestIndexData1(request);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用

    注释介绍 @Cacheable @Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 @Cacheable 作用和配置方法 参数 解释 example value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如: @Cacheable(value="mycache") @Cacheable(value={"cache1","cache2"} key 缓存的 key,可以为空,如果指定要按照

  • 解决@Cacheable在同一个类中方法调用不起作用的问题

    @Cacheable在同一类中方法调用无效 上述图片中,同一个类中genLiveBullets()方法调用同类中的queryLiveByRoom()方法,这样即便标识了Cacheable标签,再次调用时也没有走缓存. cacheable不支持内部方法调用的方式,需要修改为把请求缓存的改成service方式,Aservice中的genLiveBullets()调用Bservice中的queryLiveByRoom() 见下图,已测试再次调用时为走的缓存. @Cacheable的使用总结 @Cach

  • springboot增加注解缓存@Cacheable的实现

    目录 springboot增加注解缓存@Cacheable 业务层使用 配置 @Cacheable注解的属性使用 cacheNames和value key keyGenerator keyGenerator condition unless(除非) sync springboot增加注解缓存@Cacheable 业务层使用 @Cacheable(value = "dictionary#1800", key = "#root.targetClass.simpleName +':

  • Spring @Cacheable注解类内部调用失效的解决方案

    目录 @Cacheable注解类内部调用失效 @Cacheable注解缓存方法内部调用 方法一 方法二 方法三 方法四 @Cacheable注解类内部调用失效 如果你只是想使用一个轻量级的缓存方案,那么可以尝试使用Spring cache方案. 那么在使用spring @Cacheable注解的时候,要注意,如果类A的方法f()被标注了@Cacheable注解,那么当类A的其他方法,例如:f2(),去直接调用f()的时候,@Cacheable是不起作用的,原因是@Cacheable是基于spri

  • Spring @Cacheable注解中key的使用详解

    目录 Spring @Cacheable注解中key使用 下面是几个使用参数作为key的示例 condition属性指定发生的条件 @CachePut @CacheEvict allEntries属性 beforeInvocation属性 @Caching 使用自定义注解 @Cacheable 拼接key Spring @Cacheable注解中key使用 key属性是用来指定Spring缓存方法的返回结果时对应的key的.该属性支持SpringEL表达式.当我们没有指定该属性时,Spring将

  • 基于spring @Cacheable 注解的spel表达式解析执行逻辑

    目录 直接进入主题 跟随spring的调用链 直接看 @Cacheable 注解就可以了 接下来看 key获取是在哪里 没有任何逻辑就是一个组装 了解一下@Cacheable的拦截顺序 接下来看 execute方法 再看 重载方法execute 日常使用中spring的 @Cacheable 大家一定不陌生,基于aop机制的缓存实现,并且可以选择cacheManager具体提供缓存的中间件或者进程内缓存,类似于 @Transactional 的transactionManager ,都是提供了一

  • SpringBoot使用AOP,内部方法失效的解决方案

    目录 SpringBoot使用AOP,内部方法失效 AOP切面 现在有两个方法 写一个简单的动态代理的例子 SpringBoot使用AOP,内部方法失效 最近在使用AOP的时候,发现一个问题,普通的方法AOP就能够有用,而内部调用的方法AOP就会失效,下面重现下问题 AOP切面 @Aspect @Component public class AuthorityAspect { @Pointcut("execution(* authority.service.AuthorityService.ge

  • 解决spring AOP中自身方法调用无法应用代理的问题

    目录 spring AOP中自身方法调用无法应用代理 如下例 可以使用如下两种方式修改代码以应用事务 (1)在MyServiceImpl中声明一个MyService对象 (2)使用AopContext类 spring aop 内部方法调用事务不生效 方法1: 方法2: spring AOP中自身方法调用无法应用代理 如下例 public class MyServiceImpl implements MyService { public void do(){ //the transaction a

  • Spring AOP注解失效的坑及JDK动态代理

    @Transactional @Async等注解不起作用 之前很多人在使用Spring中的@Transactional, @Async等注解时,都多少碰到过注解不起作用的情况. 为什么会出现这些情况呢?因为这些注解的功能实际上都是Spring AOP实现的,而其实现原理是通过代理实现的. JDK动态代理 以一个简单的例子理解一下JDK动态代理的基本原理: //目标类接口 public interface JDKProxyTestService { void run(); } //目标类 publ

  • Spring @Transactional注解失效解决方案

    这篇文章主要介绍了Spring @Transactional注解失效解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性 先来了解一下@Transactional注解事务的特性吧,可以更好排查问题 1.service类标签(一般不建议在接口上)上添加@Transactional,

  • 解决Spring AOP 同类调用失效问题

    目录 背景 一 目标 二 概述 三 工作中遇到的实例 1.源代码 2.原因分析 四 解决方法 1.方法一 2.方法二 原理: 3.方法三 4.总结 背景 当初刚到公司实习不久,就遇到一个问题:在同一个类中,调用有@redis,@Transactional的方法,发现注解失效了.因为这个问题,我当时纠结了很久.最后,还是老大一语惊醒梦中人,归根结底,还是Spring Aop原理没有理解彻底.今天就来聊一下关于"Spring AOP 同类调用失效问题". 一 目标 深入探究"Sp

  • Spring @async方法如何添加注解实现异步调用

    这篇文章主要介绍了Spring @async方法如何添加注解实现异步调用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在我们使用spring框架的过程中,在很多时候我们会使用@async注解来异步执行某一些方法,提高系统的执行效率.今天我们来探讨下 spring 是如何完成这个功能的. spring 在扫描bean的时候会扫描方法上是否包含@async的注解,如果包含的,spring会为这个bean动态的生成一个子类,我们称之为代理类(?),

随机推荐