• spring-cache使用简介


    spring-cache使用简介

    简介

    缓存是实际工作中经常使用的一种提高性能的方法, 我们会在很多场景下来使用缓存,而spring-cache就是一种简单的实现。阅读本文你应该能够短时间内掌握spring带来的强大缓存技术,在非常少的配置下就可以给既有代码提供缓存能力。

    配置

    首先自行引用spring的jar包

    1. spring-cache.xml

      <?xml version="1.0" encoding="UTF-8"?>
      


    <cache:annotation-driven cache-manager="cacheManager"/>












    ```

    1. SpringCache.java

      package com.yaojiafeng.common.cache;
      
      import org.springframework.cache.annotation.CacheEvict;
      import org.springframework.cache.annotation.Cacheable;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      /**
      * Created by yaojiafeng on 2017/4/18 下午3:22.
      */
      public class SpringCache {
      
      /**
      * 加缓存
      * <p>
      * value=data 代表1级key 从EhCacheCacheManager获取Cache
      * key=#id 代表2级key 从Cache获取
      *
      * @param id
      * @return
      */
      @Cacheable(value = "data", key = "#id")
      public String getData(String id) {
      return id + ":" + System.currentTimeMillis();
      }
      
      /**
      * 清缓存
      *
      * @param id
      */
      @CacheEvict(value = "data", key = "#id")
      public void setData(String id) {
      }
      
      public static void main(String[] args) {
      ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("/cache/spring-cache.xml");
      SpringCache springCache = (SpringCache) classPathXmlApplicationContext.getBean("springCache");
      String data = springCache.getData("1");
      System.out.println(data);
      data = springCache.getData("1");
      System.out.println(data);
      springCache.setData("1");
      String data1 = springCache.getData("1");
      System.out.println(data1);
      String data2 = springCache.getData("2");
      System.out.println(data2);
      }
      }
      

    运行SpringCache.java的main方法查看结果

    从结果可见第二次getData是从缓存获取,第三次getData又不是从缓存获取,测试结果正确。

    原理解析

    1. 首先解析spring xml自定义命名空间

          <cache:annotation-driven cache-manager="cacheManager"/>
      

      这行配置对应的解析类是AnnotationDrivenCacheBeanDefinitionParser(原理请搜索spring自定义命名空间的解析过程),该类的parse方法内的registerCacheAdvisor方法读取xml配置,通过AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element)并往spring容器注册了InfrastructureAdvisorAutoProxyCreator这个bean的后置处理器(用于动态代理,织入切面),并通过SpringCachingConfigurer.registerCacheAdvisor(element, parserContext)往spring容器注册BeanFactoryCacheOperationSourceAdvisor通知器(通知器包含了CacheInterceptor通知和AnnotationCacheOperationSource切点匹配器),这里特别说明默认的cache-manager="cacheManager",则通过上面的SimpleCacheManager注入,SimpleCacheManager是具体的存储缓存的地方,我们可以根据选择灵活替换。

    2. cacheManager配置

       <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
              <property name="caches">
                  <list>
                      <bean class="org.springframework.cache.concurrent.ConcurrentMapCache">
                          <constructor-arg value="data"/>
                      </bean>
                  </list>
              </property>
          </bean>
      

      cacheManager有很多实现,这里我选择最简单的SimpleCacheManager

    3. SpringCache的getData方法

      @Cacheable(value = "data", key = "#id")
      public String getData(String id) {
          return id + ":" + System.currentTimeMillis();
      }
      

      该方法加了Cacheable注解,则会在spring装载SpringCache这个bean的时候被BeanFactoryCacheOperationSourceAdvisor通知器的切点匹配到,所以我们从spring容器获取的SpringCache为动态代理的bean,织入的通知器为BeanFactoryCacheOperationSourceAdvisor,具体的通知为CacheInterceptor,所以可知调用getData方法会走CacheInterceptor的invoke方法(环绕通知),他内部会调用execute方法,从当前拦截的方法获取spring-cache的相关注解(Cacheable、CacheEvict、CachePut、Caching,每个注解都有对应的功能),并解析注解找到对应的cacheManager、cacheResolver、keyGenerator等信息,并且会通过condition配置判断当前缓存是否需要操作, getData上有Cacheable注解,该注解首先判断当前缓存有无数据有则获取,无则调用到我们的代理方法,然后插入到缓存中(详见CacheInterceptor#invoke),其中Cacheable的value属性对应具体的缓存名,key则代表缓存中的key(支持spel表达式从参数动态生成key).

    4. SpringCache的setData方法

      @CacheEvict(value = "data", key = "#id")
      public void setData(String id) {
      }
      

      该方法加了CacheEvict注解,也会被BeanFactoryCacheOperationSourceAdvisor的切点匹配到,然后走CacheInterceptor拦截器,再调用代理类的方法后,清除对应的缓存。

    5. 核心代码

      所有的加缓存,清缓存等操作都在此方法实现。

    6. 概括总结

      spring-cache延续了注解和AOP搭配使用的风格,与spring事务如出一辙,不管是xml配置和注入的bean都大同小异,所以核心知识点如下:

      • spring自定义命名空间
      • AOP
  • 相关阅读:
    php memcache分布式和要注意的问题
    PHP延迟静态绑定(本文属于转发)
    WebSocket实战
    HTML5本地存储(Local Storage) 的前世今生
    HTML5本地存储——IndexedDB
    HTML5 FileReader
    HTML5 FormData对象
    2017-2018-1 20155225 实验四 外设驱动程序设计
    2017-2018-1 20155225 《信息安全系统设计基础》第十一周学习总结
    Linux下的IPC机制
  • 原文地址:https://www.cnblogs.com/yaojf/p/10833647.html
Copyright © 2020-2023  润新知