Spring Cache + Redis配置备忘

在网上找了一些文章,可能是比较老了,都比较麻烦,还要自己写一个Cache接口的Redis实现类,然后配置到Spring自带的CacheManager中。
其实Redis里面已经自带了CacheManager接口和Cache接口的实现,以下两种方式都可以直接配置使用,完全不必自己写代码实现。
配置好了之后就可以在代码中使用@Cacheable等注解直接标注到需要缓存的方法上,可以零耦合的使用Redis缓存,非常方便优雅。
注意:下面配置文件中超时时间的单位均为秒,0表示永不超时

第一种方式,直接使用Redis自带的CacheManager
* 优势:简单直观,效率高
* 劣势:系统中只能用Redis一种缓存了
   <!-- Redis缓存配置,这里没什么好说的,网上都有 -->
    <bean id="redisPoolConfig" 
          class="redis.clients.jedis.JedisPoolConfig"
          p:maxIdle="${redis.maxIdle}"
          p:maxTotal="${redis.maxActive}" 
          p:maxWaitMillis="${redis.maxWait}" 
          p:testOnBorrow="${redis.testOnBorrow}" />  
  
    <bean id="redisConnectionFactory"  
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
          p:poolConfig-ref="redisPoolConfig"  
          p:hostName="${redis.host}"
          p:port="${redis.port}"
          p:password="${redis.password}" 
          p:timeout="${redis.timeout}" />  

    <!-- 配置序列化器,这个JDK的是最快的,不过序列化出来的字符串会比较长 -->
    <bean id="valueSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
 
    <!-- redis template,被后面的RedisCacheManager或RedisCache引用 -->
    <bean id="redisTemplate"
          class="org.springframework.data.redis.core.StringRedisTemplate"
          p:connectionFactory-ref="redisConnectionFactory" 
          p:valueSerializer-ref="valueSerializer" />
 
    <!-- 允许基于注解的使用,proxy-target-class默认为false,即使用JDK Proxy机制,如设置为true则基于CGLIB动态生成代理类 -->
    <cache:annotation-driven cache-manager="cacheManager" />
    <!-- 使用Redis自带的CacheManager,需要传入构造参数。usePrefix必须打开,否则@Cacheable的value不起作用 -->
    <bean id="cacheManager" 
          class="org.springframework.data.redis.cache.RedisCacheManager"
          p:usePrefix="true"
          p:defaultExpiration="3600">
        <constructor-arg><ref bean="redisTemplate"/></constructor-arg>
        <!-- 下面列表每一项对应一个Cache对象的名字,也就是@Cacheable的value指向的值 -->
        <constructor-arg>
            <list>
                <value>default</value><!-- 缓存名,在注解中用value引用 -->
                <value>user</value><!-- 可以配置多个缓存,以实现不同的超时策略 -->
            </list>
        </constructor-arg>
        <!-- 用expires属性分别配置其超时时间,缺省则使用defaultExpiration,单位均为秒 -->
        <property name="expires">
            <map>
                <entry key="user" value="0"/><!-- 此缓存永不超时,即使Redis重启也不会丢失哟 -->
            </map>
        </property>
    </bean>


第二种方式,使用Spring内置CacheManager, 内部使用RedisCache对象
* 优势:可以配置使用多种不同缓存,比如ehcache+redis
* 劣势:发现cacheName和key是用一个单独的缓存项实现的,推测其查询一次需要读取两次缓存,效率略低
    <!-- 前面一样,仅替换掉cacheManager的定义 -->
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">    
        <property name="caches">    
            <set>    
                <bean class="org.springframework.data.redis.cache.RedisCache"><!-- 这个类没有默认构造方法 -->
                    <constructor-arg index="0" name="name"><value>default</value></constructor-arg><!-- 缓存名,在注解中用value引用 -->
                    <constructor-arg index="1" name="prefix"><null/></constructor-arg>
                    <constructor-arg index="2" name="redisOperations"><ref bean="redisTemplate"/></constructor-arg>
                    <constructor-arg index="3" name="expiration"><value>3600</value></constructor-arg>
                </bean>  
            </set>    
         </property>    
     </bean>

关于@Cacheable等注解的使用
* 因为Spring基于JDK Proxy或CGLIB动态产生代理类的实现机制,因此在同一个类中调用带注解的方法时,@Cachable等注解不起作用
* 推荐的方式,把可缓存的方法放在接口中,比如Service接口或Dao接口
* 如果不用接口,则也要把这些可缓存的方法放在单独的类中
* 另外这个类一定要置于Spring容器的管理之下,自己直接创建该类实例是不起作用的

例子
@Component
public interface UserService {
    @Cacheable("user") // 只有一个参数,可以省略key,直接用参数作为key,这里的value = "user"对应配置文件中的Cache对象名
    User getUser(String userId);
    @CachePut(value = "user", key = "#user.id")  // 注意必须返回对象,才会被放入缓存中,这里的key可以是spEL表达式
    User addUser(User user);
    @CacheEvict(value = "user", key = "#userId")  // 删除用户并清除缓存
    void deleteUser(String userId);
}

在UserService的实现类中,正常编写数据库访问逻辑即可,不必编写任何缓存相关代码。
Spring容器在创建Bean实例的时候,会通过Proxy或CGLIB把你的实现类的相关方法包装一层,来实现缓存机制。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值