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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM