《Spring實戰》-第十三章:緩存數據(1)-Spring對緩存的支持

慢來比較快,虛心學技術

緩存( Caching )可以存儲經常會用到的信息,這樣每次需要的時候,這些信息都是立即可用的。我們將會瞭解到 Spring 的緩存抽象。儘管 Spring 自身並沒有實現緩存解決方案,但是它對緩存功能提供了聲明式的支持,能夠與多種流行的緩存實現進行集成

Ⅰ、開啓緩存支持

  • 註解開啓:@EnableCaching
  • 配置開啓: <cache:annotation-driven>

兩種開啓方法的工作方式是相同的。它們都會創建一個切面( aspect )並觸發Spring 緩存註解的切點( pointcut )。根據所使用的註解以及緩存的狀態,這個切面會從緩存中獲取數據,將數據添加到緩存之中或者從緩存中移除某個值。

import org.springframework.cache.annotation.EnableCaching;
@Configuration
@EnableCaching
public class CacheConfig {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
     <!--啓用緩存註解功能,這個是必須的,否則註解不會生效-->
     <!--有一個cache-manager屬性用來指定當前所使用的CacheManager對應的bean的名稱,默認是cacheManager-->
     <cache:annotation-driven/>
</beans>

Ⅱ、配置緩存管理器

緩存管理器:是 Spring 緩存抽象的核心,它能夠與多個流行的緩存實現進行集成

Spring內置了多個緩存管理器:

  • SimpleCacheManager
  • NoOpCacheManager
  • ConcurrentMapCacheManager----------默認使用的緩存管理器
  • CompositeCacheManager
  • EhCacheCacheManager-------------------較常用
  • RedisCacheManager (來自於 Spring Data Redis 項目)-----------------較常用
  • GemfireCacheManager (來自於 Spring Data GemFire 項目)

1、配置ConcurrentMapCacheManager

①註解配置

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class ConcurrentMapCacheConfig {
    @Bean
    public CacheManager cacheManager1(){
        return new ConcurrentMapCacheManager();
    }
}

②XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <cache:annotation-driven/>
    <!--定義緩存管理器-->
    <bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager">
    </bean>
</beans>

2、配置EhCacheCacheManager

EhCache 是一個純Java的進程內緩存框架,具有快速、精幹等特點,是Hibernate中默認的CacheProvider

緩存數據有三級:內存、堆外緩存Off-Heap、Disk緩存,因此無需擔心容量問題。還可以通過RMI、可插入API等方式進行分佈式緩存。

緩存數據會在虛擬機重啓的過程中寫入磁盤,持久化。

具有緩存和緩存管理器的偵聽接口。

支持多緩存管理器實例,以及一個實例的多個緩存區域。

由於Spring只是提供了基本的管理器接口,還需要依賴於ehcache的第三方cache實現管理

引入依賴:

<!-- 引入Spring對cache的支持 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${org.springframework.version}</version>
    <scope>compile</scope>
</dependency>

<!-- 引入ecache支持 -->
<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.10.3</version>
</dependency>

①註解配置,此處使用的CacheManager是ehcache的緩存管理器

import net.sf.ehcache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableCaching
public class EhCacheConfig {
    /**
     * 定義緩存管理器,EhCacheCacheManager是Spring提供的管理器支持,需要將ecache的緩存管理器注入到EhCacheCacheManager中
     **/
    @Bean
    public EhCacheCacheManager cacheManager2(CacheManager cm){
        return new EhCacheCacheManager(cm);
    }

    /**
     * 定義緩存管理器工廠,用於生產EhCacheManager
     **/
    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){
        EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean();
        factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        return factoryBean;
    }
}

②XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <cache:annotation-driven/>

    <!--定義緩存管理器-->
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehcache"></property>
   </bean>

    <!--定義緩存管理器工廠-->
    <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath*:ehcache.xml"></property>
    </bean>
</beans>

其中,ehcache.xml配置文件簡單配置如下:

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <!--
        maxElementsOnDisk:磁盤緩存中最多可以存放的元素數量,0表示無窮大  
        maxElementsInMemory:內存緩存中最多可以存放的元素數量,若放入Cache中的元素超過這個數值,則有以下兩種情況  
                             1)若overflowToDisk=true,則會將Cache中多出的元素放入磁盤文件中  
                             2)若overflowToDisk=false,則根據memoryStoreEvictionPolicy策略替換Cache中原有的元素  
         eternal:緩存中對象是否永久有效,即是否永駐內存,true時將忽略timeToIdleSeconds和timeToLiveSeconds
         timeToIdleSeconds:緩存數據在失效前的允許閒置時間(單位:秒),僅當eternal=false時使用,默認值是0表示可閒置時間無窮大,此爲可選屬性  
                             即訪問這個cache中元素的最大間隔時間,若超過這個時間沒有訪問此Cache中的某個元素,那麼此元素將被從Cache中清除  
        timeToLiveSeconds:緩存數據在失效前的允許存活時間(單位:秒),僅當eternal=false時使用,默認值是0表示可存活時間無窮大  
                             即Cache中的某元素從創建到清楚的生存時間,也就是說從創建開始計時,當超過這個時間時,此元素將從Cache中清除
        overflowToDisk:內存不足時,是否啓用磁盤緩存(即內存中對象數量達到maxElementsInMemory時,Ehcache會將對象寫到磁盤中)  
                             會根據標籤中path值查找對應的屬性值,寫入磁盤的文件會放在path文件夾下,文件的名稱是cache的名稱,後綴名是data  
        diskPersistent:是否持久化磁盤緩存,當這個屬性的值爲true時,系統在初始化時會在磁盤中查找文件名爲cache名稱,後綴名爲index的文件  
                             這個文件中存放了已經持久化在磁盤中的cache的index,找到後會把cache加載到內存  
                             要想把cache真正持久化到磁盤,寫程序時注意執行net.sf.ehcache.Cache.put(Element element)後要調用flush()方法
    -->
    <defaultCache
            maxElementsInMemory="1000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"/>
    <!--定義一個緩存-->
    <cache name="ehCache"
           maxElementsOnDisk="20000"
           maxElementsInMemory="2000"
           eternal="false"
           overflowToDisk="true"
           diskPersistent="true"/>

</ehcache>

3、配置RedisCacheManager

Redis 可以用來爲 Spring 緩存抽象機制存儲緩存條目, Spring Data Redis 提供了 RedisCacheManager ,這是 CacheManager 的一個實現。

RedisCacheManager 會與一個 Redis 服務器協作,並通過 RedisTemplate 將緩存條目存儲到 Redis 中

上一節已經瞭解過Redis,此處我們需要先引入Redis支持:

<!--引入Spring Data Redis-->
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.1.5.RELEASE</version>
</dependency>

<!--引入jedis支持-->
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.1</version>
</dependency>

①混合配置

application-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <cache:annotation-driven cache-manager="redisCacheManager"/>
</beans>

RedisConfig.java

@Configuration
@ComponentScan(basePackages = {"com.my.spring.dao"})
@ImportResource("classpath:application-redis.xml")//引入配置文件
@EnableCaching
public class RedisCacheConfig {

    /**
     * 定義緩存管理器,注入redisConnectionFactory
     * @param redisConnectionFactory
     * @return
     */
    @Bean("redisCacheManager")
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
        RedisCacheManager.RedisCacheManagerBuilder builder = 
                    RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory);
        Set<String> cacheNames = new HashSet<String>() {{
            add("myCache");
        }};
        //設置多個緩存
        builder.initialCacheNames(cacheNames);
        return builder.build();
    }

    /**
     * 定義Redis連接工廠
     * @return
     */
    @Bean
    public JedisConnectionFactory redisConnectionFactory(){
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.afterPropertiesSet();
        return factory;
    }
}

四、混合使用多種緩存CompositeCacheManager

我們並不是只能有且僅有一個緩存管理器。如果你很難確定該使用哪個緩存管理器,或者有合法的技術理由使用超過一個緩存管理器的話,那麼可以嘗試使用 Spring 的 CompositeCacheManager.CompositeCacheManager 要通過一個或更多的緩存管理器來進行配置,它會迭代這些緩存管理器,以查找之前所緩存的值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章