springboot cache缓存注解源码解析

springboot中带有与缓存相关的注解分别是:
1.Cacheable
对于Cacheable注解的方法,执行该方法时首先从相应的缓存中寻找数据,如果找到则将缓存中的数据作为方法的执行结果返回;如果没有找到,则执行该方法,并将执行结果放入缓存。
2.CachePut
对于CachePut注解的方法,执行该方法时会将方法的执行结果更新入缓存。
3.CacheEvict
对于CacheEvict注解的方法,执行该方法时会删除对应的缓存。
4.Caching
包含了上述3个注解。

要在springboot中使用上述的缓存注解,需要在项目中加上@EnableCaching注解。EnableCaching中通过@import注解引入CachingConfigurationSelector类,将AutoProxyRegistrar类和ProxyCachingConfiguration注入IOC容器。
AutoProxyRegistrar是自动代理生成器,与EnableProxyTargetClass的proxyTargetClass和AdviceMode相关,AdviceMode为PROXY则需要注册APC,proxyTargetClass为true则必须使用CGLIB代理。EnableCaching暴露了代理的属性,因此这个类主要是为了确定属性正确。
ProxyCachingConfiguration是缓存相关的配置类,使我们分析的重点,ProxyCachingConfiguration注入了3个bean类BeanFactoryCacheOperationSourceAdvisor、CacheOperationSource和CacheInterceptor。CacheOperationSource类在CacheInterceptor注入时进行了使用,其它地方并没有什么作用。
首先看CacheInterceptor方面,该方法是缓存注解的拦截器,也就是我们通常说的AOP中的通知,根据AbstractCachingConfiguration的setConfigurers方法我们能看出,我们可以通过一个注入IOC容器的实现CachingConfigurer接口的类来指定CacheInterceptor的一些属性,作为后续缓存操作的默认属性,CacheResolver和CacheManager都对应CacheInterceptor的CacheResolver属性,用来指定使用的缓存工具,keyGenerator用来指定生成缓存key的keyGenerator类,errorHandler用来指定出错时的异常处理。事实上,大多数springboot中AOP注解的通过都是通过这种方式来实现advice的元素的配置化的。

@Autowired(required = false)
void setConfigurers(Collection<CachingConfigurer> configurers) {
	if (CollectionUtils.isEmpty(configurers)) {
		return;
	}
	if (configurers.size() > 1) {
		throw new IllegalStateException(configurers.size() + " implementations of " +
				"CachingConfigurer were found when only 1 was expected. " +
				"Refactor the configuration such that CachingConfigurer is " +
				"implemented only once or not at all.");
	}
	CachingConfigurer configurer = configurers.iterator().next();
	useCachingConfigurer(configurer);
}

然后看BeanFactoryCacheOperationSourceAdvisor,这是一个PointcutAdvisor类,包含了advice元素和pointcut元素,将advice注入pointcut。BeanFactoryCacheOperationSourceAdvisor类中的advice即为CacheInterceptor,接下来我们看pointcut的值。

private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() {
	@Override
	@Nullable
	protected CacheOperationSource getCacheOperationSource() {
		return cacheOperationSource;
	}
};

进入抽象类CacheOperationSourcePointcut查看其中关键的matches方法,该方法返回为true的连接点就是我们的pointcut,即cas.getCacheOperations(method, targetClass)返回的集合不为空。

@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
	CacheOperationSource cas = getCacheOperationSource();
	return (cas != null && !CollectionUtils.isEmpty(cas.getCacheOperations(method, targetClass)));
}
@Override
@Nullable
public Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass) {
	if (method.getDeclaringClass() == Object.class) {
		return null;
	}

	Object cacheKey = getCacheKey(method, targetClass);
	Collection<CacheOperation> cached = this.attributeCache.get(cacheKey);

	if (cached != null) {
		return (cached != NULL_CACHING_ATTRIBUTE ? cached : null);
	}
	else {
		Collection<CacheOperation> cacheOps = computeCacheOperations(method, targetClass);
		if (cacheOps != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Adding cacheable method '" + method.getName() + "'
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值