Spring?@Cacheable注解類內(nèi)部調(diào)用失效的解決方案
@Cacheable注解類內(nèi)部調(diào)用失效
如果你只是想使用一個輕量級的緩存方案,那么可以嘗試使用Spring cache方案。
那么在使用spring @Cacheable注解的時候,要注意,如果類A的方法f()被標(biāo)注了@Cacheable注解,那么當(dāng)類A的其他方法,例如:f2(),去直接調(diào)用f()的時候,@Cacheable是不起作用的,原因是@Cacheable是基于spring aop代理類,f2()屬于內(nèi)部方法,直接調(diào)用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注解緩存方法內(nèi)部調(diào)用
因為Spring Cache是基于切面的(基于AOP的動態(tài)代理實現(xiàn)的:即都在方法調(diào)用前后去獲取方法的名稱、參數(shù)、返回值,然后根據(jù)方法名稱、參數(shù)生成緩存的key(自定義的key例外),進(jìn)行緩存),所以內(nèi)部方法調(diào)用不會調(diào)用切面,導(dǎo)致緩存不生效
方法一
暴露Aop代理到ThreadLocal支持,在類之前加@EnableAspectJAutoProxy(exposeProxy = true)
調(diào)用的時候使用((XxxService) AopContext.currentProxy()).method()調(diào)用方法
eg:
ApiBaseResponse<ApiPageResponse<RoadCongestIndexData>> apiPageResponseApiBaseResponse = ? ? ? ? ? ? ? ? ((RoadLastPageServiceImpl) AopContext.currentProxy()).queryLastPageCongestIndexData1(request);
方法二
把需要用緩存的方法單獨寫到一個類里面,把內(nèi)部調(diào)用變成類間調(diào)用
RoadLastPageServiceImpl selfService = SpringContextUtil.getBean(RoadLastPageServiceImpl.class); ? ? ? ? selfService.queryLastPageCongestIndexData1(request);
方法三
類自我注入,使用@lazy和@Autowired注解實現(xiàn)自我注入,然后使用時用注解的實例代替this調(diào)用方法。
@Lazy @Autowired private RoadLastPageServiceImpl serviceImplCache;
方法四
寫一個工具類,使用內(nèi)部調(diào)用的時候,自己實例化一個對象,讓類走AOP
@Component public class SpringContextUtil implements ApplicationContextAware { ? ? private static ApplicationContext applicationContext; ? ? /** ? ? ?* 實現(xiàn)ApplicationContextAware接口的回調(diào)方法,設(shè)置上下文環(huán)境 ? ? ?* ? ? ?* @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); ? ? } }
調(diào)用的時候這么調(diào)用
RoadLastPageServiceImpl selfService = SpringContextUtil.getBean(RoadLastPageServiceImpl.class); selfService.queryLastPageCongestIndexData1(request);
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題
這篇文章主要介紹了Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Spring5源碼解析之Spring中的異步和計劃任務(wù)
本篇文章主要介紹了Spring5源碼解析之Spring中的異步和計劃任務(wù),具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-10-10SpringCloud集成Eureka并實現(xiàn)負(fù)載均衡的過程詳解
這篇文章主要給大家詳細(xì)介紹了SpringCloud集成Eureka并實現(xiàn)負(fù)載均衡的過程,文章通過代碼示例和圖文講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的參考價值,需要的朋友可以參考下2023-11-11springboot+chatgpt+chatUI Pro開發(fā)智能聊天工具的實踐
本文主要介紹了springboot+chatgpt+chatUI Pro開發(fā)智能聊天工具的實踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04