专注JavaWeb开发 首页制式『默认式 OR 时间轴 网站地图|RSS订阅|设为首页|加入收藏
当前位置:首页 >Java >JavaEE初级 > 正文

@Cacheable注解调用失效

作者: 紫寒1120 发布时间: 2017-05-27 浏览次数:

最近在做"专注网"开发,使用cache失效 代码如下

@Override
	public Map getFirmStatistics(String id, Long firmId) {
		Map map = new HashMap();
		String key = "firmstatistics:" + id + ":" + firmId;
		NumberFormat ddf1 = NumberFormat.getNumberInstance();
		ddf1.setMaximumFractionDigits(0);
		Set<Tuple> strings = redisClientTemplate.zrangeWithScores(key, 0, -1, 3);
		for (Tuple tuple : strings) {
			map.put(tuple.getElement(), ddf1.format(tuple.getScore()));
		}
		//失效不会走cache
		FirmStatistics firmStatistics = selectByAttrId(firmId);
		// 计算系数
		double score = firmStatistics.getEnvironmentScore() / firmStatistics.getEnvironmentCount() * 0.1 + firmStatistics.getPressureScore() / firmStatistics.getPressureCount()
				* 0.2 + firmStatistics.getManageScore() / firmStatistics.getManageCount() * 0.3 + firmStatistics.getSincerityScore() / firmStatistics.getSincerityCount() * 0.4;
		ddf1.setMaximumFractionDigits(1);
		map.put("score", ddf1.format(score));
		// 查看次数
		map.put("readTimes", firmStatistics.getReadTimes());
		// 评论次数
		map.put("commentCount", firmStatistics.getCommentCount());
		return map;
	}

	@Override
	@Cacheable(value = "selectByAttrId")
	public FirmStatistics selectByAttrId(Long firmId) {
		FirmStatisticsVo firmStatisticsVo = new FirmStatisticsVo();
		firmStatisticsVo.setAttrId(firmId);
		return selectByStatement(firmStatisticsVo).get(0);
	}

原因如下:

@Cacheable是基于spring aop代理类,内部方法调用注解的方法,是不走代理的.

解决方法:

在控制层先查询缓存的方法,再去调用不缓存的方法

方法改为:

@Override
	public Map getFirmStatistics(String id, Long firmId,FirmStatistics firmStatistics) {
		Map map = new HashMap();
		String key = "firmstatistics:" + id + ":" + firmId;
		NumberFormat ddf1 = NumberFormat.getNumberInstance();
		ddf1.setMaximumFractionDigits(0);
		....
		}



(参考别人的网站)

如果你只是想使用一个轻量级的缓存方案,那么可以尝试使用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方法抽取到另外的类中,例如:

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

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





QQ群: 武汉地区(142173356)验证消息JavaWeb1024

网友共有【】评论,点击查看



x 微信关注我们 随时获取最新网站资讯