Spring Cacheb的使用及实现原理

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> Spring Cacheb的使用及实现原理

Spring Cacheb的使用及实现原理

从Spring 3.1版本开始,提供了一种透明的方式来为现有的Spring 应用添加cache,使用起来就像@Transaction一样。在应用层面与后端存储之间,提供了一层抽象,这层抽象目的在于封装各种可插拔的后端存储( Ehcache Guava Redis),最小化因为缓存给现有业务代码带来的侵入。

正如Spring框架的其它服务一样,Spring cache 首先是提供了一层抽象,核心抽象主要体现在两个接口上

org.springframework.cache.Cache

org.springframework.cache.CacheManager

Cache代表缓存本身

CacheManager代表对缓存的处理和管理等。抽象的意义在于屏蔽实现细节的差异和提供扩展性,这一层Cache的抽象解耦了缓存的使用和缓存的后端存储,这样后续可以方便的更换后端存储。

  • 声明缓存
  • 开启Spring的cache功能
  • 配置后端的存储
  • @Cacheable(“books”)
    public Book findBook(ISBN isbn) {…}

    用法很简单,在方法上添加@cacheable等注解,表示缓存该方法的结果。

    当方法有被调用时,先检查cache中有没有针对该方法相同参数的调用发生过,如果有,从cache中查询并返回结果。如果没有,则执行具体的方法逻辑,并把结果缓存到cache中。当然这一系列逻辑对于调用者来说都是透明的。其它的缓存操作的注解包含如下(详细说明可参见官方文档):

  • @Cacheable triggers cache population
  • @CacheEvict triggers cache eviction
  • @CachePut updates the cache without interfering with the method execution
  • @Caching regroups multiple cache operations to be applied on a method
  • @CacheConfig shares some common cache-related settings at class-level
  • cache:annotation-driven /

    或者使用注解@EnableCaching的方式

    Spring Cache提供了几种内置的后端存储的实现:下面都是CacheManager的具体实现。

    Spring Cacheb的使用及实现原理

    此外,Spring Data提供了两个缓存管理器:

  • **RedisCacheManager**(来自于Spring Data Redis项目)
  • **GmfireCacheManager**(来自于Spring Data GemFire项目
  • GmfireCacheManager(来自于Spring Data GemFire项目

    假如使用memcached或者redis等分布式缓存的话,可以自己实现Cache和CacheManager,然后在Context里声明即可。如果需要使用到多种不同的缓存实现,可以用组合模式把各种不同的CacheManager封装在一起。

    Spring Cacheb的使用及实现原理

    我们都知道缓存的存储方式一般是key value的方式,那么在Spring cache里,key是如何被设置的呢,在这里要引入KeyGenerator,它负责key的生成策略,默认的使用SimpleKeyGenerator

    Spring Cacheb的使用及实现原理 Spring Cacheb的使用及实现原理

    能看出来,其中就是有序参数数组的hash值。当然用户可以自定义key生成策略。

    上面是Spring cache的大致使用方式,来看是Spring是如何实现的。

    在学习Spring源码的时候,有两点可以记住:

  • 大多数高级功能的实现都依赖Spring AOP
  • 大多数功能的组装时机都依赖Sprin bean生命周期中的几个回调接口
  • 记住了这些就比较容易理解Spring中的一些组件的实现及运行时机制

    Spring cache也不例外,它是典型的Spring AOP实现,在Spring里,aop可以简单的理解为代理(AspectJ除外),我们声明了@Cacheable的方法的类,都会被代理,在代理中,实现缓存的查询与设置操作。

    上一篇()谈到过,Spring AOP的创建过程,本质是实现了一个BeanPostProcessor,在创建bean的过程中创建proxy,并且为proxy绑定所有适用于该bean的advisor,最终暴露给容器。

    Spring中AOP主几个关键的概念 advisor  advice pointcut

    advice = 切面拦截中插入的行为

    pointcut = 切面的切入点

    advisor = advice + pointcut

    Spring cache也同样与其它aop有类似的过程

    创建 cache proxy

  • 由**InfrastructureAdvisorAutoProxyCreator**负责的,它实现**BeanPostProcessor**所以可以在bean实例化返回给容器前有机会创建代理,它又继承了**AbstractAdvisorAutoProxyCreator**,所以又具备了给代理类绑定advisor的能力。
  • pointcut的职责是由**CacheOperationSourcePointcut**完成的,它主要是通过方法上的cache相关的注解来判断匹配是否需要切入
  • Spring cache中生成cache代理对象使用的是CacheProxyFactoryBean工厂类。一般来说,在Spring中标准代理的创建都是基于ProxyFactoryBean,在这里,为了更方便的处理cache逻辑,Spring引入了CacheProxyFactoryBean来专门表示cache相关的代理,cache proxy能wrapper单例目标对象,并且代理目标对象实现的所有接口。

    Spring Cacheb的使用及实现原理

    可以看到,在CacheProxyFactoryBean中,有个重要的属性是CacheInterceptor,这个类是一个MethodInterceptor的实现类,这个类的职责是在目标对象目标方法上执行具体缓存操作,这也就是上面提到的advice的职责。

    Spring Cacheb的使用及实现原理

    继续往下跟,return 的execute方法是父类CacheAspectSupport中的方法

    Spring Cacheb的使用及实现原理

    在这个方法里,我们最终找到的操作缓存的最终逻辑

  • 判断缓存条件
  • 获取key
  • 获取cache
  • 最终调用cache.get(key, Callable)方法,第二个参数是一个回调,用于处理没有命中缓存的情况: **if cached, return; otherwise create, cache and return**

  • Spring Cacheb的使用及实现原理

    SpringAutowired

    一个有用的公众号

    Spring Cacheb的使用及实现原理Spring Cacheb的使用及实现原理

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> Spring Cacheb的使用及实现原理


     上一篇
    Spring AOP 模块概述 Spring AOP 模块概述
    概述 AOP从功能的角度来讲,可能看作OOP编程方式的一种补充,提供了一种不同的代码或者系统组织方式。OOP中的核心概念是Class,而在AOP中则是Aspect。 spirng-aop模块是Spring框架中的核心模块,虽然Sp
    2021-04-05
    下一篇 
    Spring-Java配置形式讲解 Spring-Java配置形式讲解
    前言: 最初的sprng1.x开始,spring一直使用的是xml配置的形式。而从spring2.x因为jdk5的发布也引入了注解的形式Java代码类配置形式则是Spring3.x出现的功能。springboot的配置形式多数使用 是ja
    2021-04-05