如图所示,getRecomendGoogs方法里面调用findImgUrlByName方法,在findImgUrlByName方法上使用@Cacheable注解的时候,并没有走缓存。
要解决这个问题,首先我们需要了解spring缓存的原理。spring cache的实现原理跟spring的事物管理类似,都是基于AOP的动态代理实现的:即都在方法调用前后
去获取方法的名称、参数、返回值,然后根据方法名称、参数生成缓存的key(自定义的key例外),进行缓存。debug可以看到调用的实际上是groupUserBiz
的代理类,基于cglib动态代理实现。当调用代理的方法时,代理可以整体控制实际的方法的入参和返回值。比如缓存结果,直接跳过执行实际的方法等。
找到了原因之后,我们有两种解决方案
第一种:
把findImgUrlByName这个方法单独写到另外的一个类里面去,把内部调用搞成内间调用
第二种:
使用内部调用的时候,自己实例化一个类对象,让类走AOP,
写一个工具类
@Component
public class SpringContextUtil implements ApplicationContextAware {
// Spring应用上下文环境
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
*
* @param applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* @return 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);
}
}
在getRecomendGoogs方法调用findImgUrlByName的时候使用
WeCommonService weCommonService = SpringContextUtil.getBean(WeCommonService.class);自己实例化service