这个类实现了Spring的缓存拦截器 org.springframework.cache.interceptor.CacheInterceptor

@SuppressWarnings("serial")
public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable { private static class ThrowableWrapper extends RuntimeException {
private final Throwable original; ThrowableWrapper(Throwable original) {
this.original = original;
}
} //这是进行对目标方法的拦截
public Object invoke(final MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod(); //封装一个回调对象 多目标方法进行调用
Invoker aopAllianceInvoker = new Invoker() {
public Object invoke() {
try {
return invocation.proceed();
} catch (Throwable ex) {
throw new ThrowableWrapper(ex);
}
}
}; try {
//调用父类的execute方法 进行缓存的逻辑判断处理
return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments());
} catch (ThrowableWrapper th) {
throw th.original;
}
}
}

下面分析execute方法

    protected Object execute(Invoker invoker, Object target, Method method, Object[] args) {
//判断当前对象是否已经初始化完毕
if (!this.initialized) {
return invoker.invoke();
} //获得目标类型
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
if (targetClass == null && target != null) {
targetClass = target.getClass();
}
//获得缓存操作细节对象
final Collection<CacheOperation> cacheOp = getCacheOperationSource().getCacheOperations(method, targetClass); //判断是否为空 不为空则进行下面的缓存逻辑处理
if (!CollectionUtils.isEmpty(cacheOp)) {
Map<String, Collection<CacheOperationContext>> ops = createOperationContext(cacheOp, method, args, target, targetClass); // 调用目标方法之前的清除缓存动作
inspectBeforeCacheEvicts(ops.get(EVICT)); // follow up with cacheable
CacheStatus status = inspectCacheables(ops.get(CACHEABLE)); Object retVal = null;
Map<CacheOperationContext, Object> updates = inspectCacheUpdates(ops.get(UPDATE)); if (status != null) {
if (status.updateRequired) { updates.putAll(status.cUpdates);
}
// return cached object
// 返回缓存当中的数据
else {
return status.retVal;
}
}
//调用目标对象 拿到返回值
retVal = invoker.invoke(); // 调用目标方法之后的清除缓存动作
inspectAfterCacheEvicts(ops.get(EVICT)); //更新缓存,或将返回结果放入缓存
if (!updates.isEmpty()) {
update(updates, retVal);
}
//返回结果
return retVal;
} //上面判断如果缓存操作细节对象为空 则直接调用目标对象处理。
return invoker.invoke();
}

Spring Cache 源码解析的更多相关文章

  1. spring事务源码解析

    前言 在spring jdbcTemplate 事务,各种诡异,包你醍醐灌顶!最后遗留了一个问题:spring是怎么样保证事务一致性的? 当然,spring事务内容挺多的,如果都要讲的话要花很长时间, ...

  2. Spring IoC源码解析之invokeBeanFactoryPostProcessors

    一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...

  3. Spring系列(六):Spring事务源码解析

    一.事务概述 1.1 什么是事务 事务是一组原子性的SQL查询,或者说是一个独立的工作单元.要么全部执行,要么全部不执行. 1.2 事务的特性(ACID) ①原子性(atomicity) 一个事务必须 ...

  4. Spring Security源码解析一:UsernamePasswordAuthenticationFilter之登录流程

    一.前言 spring security安全框架作为spring系列组件中的一个,被广泛的运用在各项目中,那么spring security在程序中的工作流程是个什么样的呢,它是如何进行一系列的鉴权和 ...

  5. Spring cache源码分析

    Spring cache是一个缓存API层,封装了对多种缓存的通用操作,可以借助注解方便地为程序添加缓存功能. 常见的注解有@Cacheable.@CachePut.@CacheEvict,有没有想过 ...

  6. Spring IoC源码解析之getBean

    一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...

  7. Spring系列(五):Spring AOP源码解析

    一.@EnableAspectJAutoProxy注解 在主配置类中添加@EnableAspectJAutoProxy注解,开启aop支持,那么@EnableAspectJAutoProxy到底做了什 ...

  8. Spring系列(三):Spring IoC源码解析

    一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...

  9. Spring Boot系列(四):Spring Boot源码解析

    一.自动装配原理 之前博文已经讲过,@SpringBootApplication继承了@EnableAutoConfiguration,该注解导入了AutoConfigurationImport Se ...

随机推荐

  1. shell脚本死循环判断nginx日志reqest_time时间大于3秒是否增加,若增加发送相关日志信息到开发人员

    #!/bin/bash while [ 1 ] do pre_request_time_count=`cat /var/log/nginx/access.log |awk '{print $NF}'| ...

  2. MVC图片上传、浏览、删除 ASP.NET MVC之文件上传【一】(八) ASP.NET MVC 图片上传到服务器

    MVC图片上传.浏览.删除   1.存储配置信息 在web.config中,添加配置信息节点 <appSettings> <add key="UploadPath" ...

  3. Python学习笔记015——文件file的常规操作(二进制文件)

    有时候诸如图片.音乐等信息不是以文本的形式存储的,而是二进制文件格式存储的. 有时候很多信息不是以文本文件的形式存储的 很多时候,都需要用到二进制读取文件.毕竟很多信息不是以文本的形式存储.例如:图片 ...

  4. win7 下jenkins配置与使用

    一.Jenkins的配置 1. 下载地址: Jenkins的官方网站:http://jenkins-ci.org/ 目前最新版本的Windows版:http://mirror.xmission.com ...

  5. 命名管道FIFO和mkfifo函数

    进程间通信必须通过内核提供的通道,而且必须有一种办法在进程中标识内核提供的某个通道,前面讲过的匿名管道是用打开的文件描述符来标识的.如果要互相通信的几个进程没有从公共祖先那里继承文件描述符,它们怎么通 ...

  6. php json的相关操作

    类与json <?php class userinfo { var $user_name; var $user_ip; var $user_logintime; } $u = new useri ...

  7. mysql-5.7中的innodb_buffer_pool_prefetching(read-ahead)详解

    一.innodb的read-ahead是什么: 所谓的read-ahead就是innodb根据你现在访问的数据,推测出你接下来可能要访问的数据,并把它们(可能要访问的数据)读入 内存. 二.read- ...

  8. 在 Visual Studio 2013 中使用 JavaScript 的 IntelliSense

    原本JavaScript直接在页面中引用的时候,智能感知会直接根据js文件的内容来获得提示.但是由于在新的ASP.NET中使用了Bundle,js文件不是直接在页面中引用了,所以智能感知也就出了问题. ...

  9. C/C++ 数据结构之算法(面试)

    数据结构中的排序算法. 排序算法的相关知识: (1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来. (2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的 ...

  10. [k8s]通过svc来访问集群podhttp://api:8080/api/v1/namespaces/default/services/mynginx/proxy/

    以往的套路是,安装完成k8s集群后-->安装dns-->安装ingress以便外面访问(或者映射nodeport方式) 如果你不想做任何关于ingress/nodeport一些操作.想通过 ...