这个类实现了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. Linux下编辑利器vim,vimrc,viminfo的高级用法

    1.ci" (由 change operator 和 text-object i" 组成) 这个命令会找到当前光标所在行的下一个 " 括起来的字符串,清除引号裏面的内容, ...

  2. 如何使用Dockerfile构建Tomcat镜像并部署war

    我们都知道Docker构建一个镜像有两种方式: 使用`docker commit`命令 使用`Dockerfile`文件和`docker build`命令 那么这两种方式有何区别呢? 相同点:底层实现 ...

  3. C输出大于127的ACSII字符

    近期,我们的DNS服务器收到了一些异常的域名请求,从访问日志看到很多域名都被返回了FORMAT ERROR的错误码,但是访问日志中的域名看起来很正常啊,为什么会返回FORMAT ERROR的错误码呢? ...

  4. HDUOJ----2647Reward

    Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  5. Web前端开发笔试&面试_01(mi:)

    —— (al_me16041719002000) begin—— 1.(单选)下面哪个方法是String对象和Array对象都有的? A.splice B.split C.replace D.conc ...

  6. 奇葩属性:layout_weight 的解释及使用

    在Android的控件布局中,有一个奇葩的 layout_weight 属性,定义如下: layout_weight : 用于指定剩余空闲空间的分割比例.用法: 01 <LinearLayout ...

  7. 数据库分析函数 ROW_NUMBER() rank() dense_rank() 的区别 first_value(D) , last_value(D)

    直接上图 select * from tab select B,ROW_NUMBER()over(order by B) from tab 当碰到相同数据时,排名按照记录集中记录的顺序依次递增.  遇 ...

  8. Linux下C结构体初始化

    1.前言 今天在公司看一同事写的代码,代码中用到了struct,初始化一个struct用的是乱序格式,如下代码所示: typedef struct _data_t { int a; int b; }d ...

  9. app hybrid

    package com.note.testcases; /** * * The MIT License (MIT) * * Copyright (c) 2016 Alejandro Gómez Mor ...

  10. 使用dockerfile 构建springboot 的docker镜像

    1 新建一个 springboot 项目,并将其打包成 jar 文件.生成demo1.jar 文件 请参考 使用springBoot搭建REATFul风格的web demo 2 编写 dockerfi ...