zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    设计模式系列
    Python3 系列之 可变参数和关键字参数
    设计模式系列
    【HANA系列】SAP HANA ODBC error due to mismatch of version
    【FICO系列】SAP FICO FS00修改科目为未清项目管理
    【FIORI系列】SAP OpenUI5 (SAPUI5) js框架简单介绍
    【HANA系列】SAP HANA SQL获取当前日期加若干天后的日期
    【HANA系列】SAP HANA SQL获取本周的周一
    【HANA系列】SAP HANA SQL获取当前日期
    【HANA系列】SAP HANA SQL获取当前日期最后一天
  • 原文地址:https://www.cnblogs.com/yaojf/p/10833647.html
Copyright © 2011-2022 走看看