spring 方法级缓存多种实现

方案实施

1、 spring和ehcache集成

主要获取ehcache作为操作ehcache的对象。

spring.xml中注入ehcacheManager和ehCache对象,ehcacheManager是需要加载ehcache.xml配置信息,创建ehcache.xml中配置不同策略的cache。

<!-- ehCache 配置管理器 -->

<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

<property name="configLocation" value="classpath:ehcache.xml" />

<!--true:单例,一个cacheManager对象共享;false:多个对象独立 -->

<property name="shared" value="true" />

<property name="cacheManagerName" value="ehcacheManager" />

</bean> <!-- ehCache 操作对象 -->

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">

<property name="cacheManager" ref="ehcacheManager"/>

</bean>

<!-- 启用缓存注解功能(请将其配置在Spring主配置文件中) -->

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

2、 spring和自带的缓存支持

<!-- Spring自己的基于java.util.concurrent.ConcurrentHashMap实现的缓存管理器(该功能是从Spring3.1开始提供的) -->

<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">

<property name="caches">

<set>

<bean name="SimplePageCachingFilter" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" />

</set>

</property>

</bean>

3.spring和redis集成

主要获取redisTemplate作为操作redis的对象。

redis.properties配置信息

#host 写入redis服务器地址

redis.ip=127.0.0.1

#Port

redis.port=6379

#Passord

#redis.password=123456

#连接超时30000

redis.timeout=30

#最大分配的对象数

redis.pool.maxActive=100

#最大能够保持idel状态的对象数

redis.pool.maxIdle=30

#当池内没有返回对象时,最大等待时间

redis.pool.maxWait=1000

#当调用borrow Object方法时,是否进行有效性检查

redis.pool.testOnBorrow=true

#当调用return Object方法时,是否进行有效性检查

redis.pool.testOnReturn=true

spring注入jedisPool、redisConnFactory、redisTemplate对象

<!-- 加载redis.propertis -->

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property name="locations" value="classpath:redis.properties"/>

</bean>

<!-- Redis 连接池 -->

<bean id="jedisPool" class="redis.clients.jedis.JedisPoolConfig">

<property name="maxTotal" value="${redis.pool.maxActive}" />

<property name="maxIdle" value="${redis.pool.maxIdle}" />

<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />

<property name="testOnReturn" value="${redis.pool.testOnReturn}" />

<property name="maxWaitMillis" value="${redis.pool.maxWait}" />

</bean>

<!-- Redis 连接工厂 -->

<bean id="redisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">

<property name="hostName" value="${redis.ip}" />

<property name="port" value="${redis.port}" />

<!-- property name="password" value="${redis.password}" -->

<property name="timeout" value="${redis.timeout}" />

<property name="poolConfig" ref="jedisPool" />

</bean>

<!-- redis 操作对象 -->

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">

<property name="connectionFactory" ref="redisConnFactory" />

</bean>

<!-- 自定义缓存 -->

<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">

<property name="caches">

<set>

<bean class="org.cpframework.cache.redis.RedisCache">

<property name="redisTemplate" ref="redisTemplate" />

<property name="name" value="default"/>

</bean>

</set>

</property>

</bean>

<!-- 启用缓存注解功能(请将其配置在Spring主配置文件中) -->

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

4.spring 缓存注解解释

缓存注解有以下三个:

@Cacheable @CacheEvict @CachePut

1.

@Cacheable(value=”accountCache”),这个注释的意思是,当调用这个方法的时候,会从一个名叫 accountCache 的缓存中查询,如果没有,则执行实际的方法,并将执行的结果存入缓存中,否则返回缓存中的对象。这里的缓存中的 key 就是参数 userName,value 就是 Account 对象。“accountCache”缓存是在 spring*.xml 中定义的名称。

例子:

@Cacheable(value="accountCache")// 使用了一个缓存名叫 accountCache

public Account getAccountByName(String userName) {

// 方法内部实现不考虑缓存逻辑,直接实现业务

System.out.println("real query account."+userName);

return getFromDB(userName);

}

condition:用来条件判断,满足条件的则进行缓存

例子2:

@Cacheable(value="accountCache",condition="#userName.length() <=4")// 缓存名叫 accountCache

public Account getAccountByName(String userName) {

// 方法内部实现不考虑缓存逻辑,直接实现业务

return getFromDB(userName);

}

2.

@CacheEvict 注释来标记要清空缓存的方法,当这个方法被调用后,即会清空缓存。注意其中一个 @CacheEvict(value=”accountCache”,key=”#account.getName()”),其中的 Key 是用来指定缓存的 key 的,这里因为我们保存的时候用的是 account 对象的 name 字段,所以这里还需要从参数 account 对象中获取 name 的值来作为 key,前面的 # 号代表这是一个 SpEL 表达式,此表达式可以遍历方法的参数对象

例子3:

@CacheEvict(value="accountCache",key="#account.getName()")// 清空accountCache 缓存

public void updateAccount(Account account) {

updateDB(account);

}

@CacheEvict(value="accountCache",allEntries=true)// 清空accountCache 缓存

public void reload() {

reloadAll()

}

@Cacheable(value="accountCache",condition="#userName.length() <=4")// 缓存名叫 accountCache

public Account getAccountByName(String userName) {

// 方法内部实现不考虑缓存逻辑,直接实现业务

return getFromDB(userName);

}

3.

@CachePut 注释,这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。

@CachePut(value="accountCache",key="#account.getName()")// 更新accountCache 缓存

public Account updateAccount(Account account) {

return updateDB(account);

}

附录:

@Cacheable、@CachePut、@CacheEvict 注释介绍

通过上面的例子,我们可以看到 spring cache 主要使用两个注释标签,即 @Cacheable、@CachePut 和 @CacheEvict,我们总结一下其作用和配置方法。

表 1. @Cacheable 作用和配置方法

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存


@Cacheable 主要的参数
   

value

缓存的名称,在 spring 配置文件中定义,必须指定至少一个

例如: @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}

key

缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

例如: @Cacheable(value=”testcache”,key=”#userName”)

condition

缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

例如: @Cacheable(value=”testcache”,condition=”#userName.length()>2”)

表 2. @CachePut 作用和配置方法

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用


@CachePut 主要的参数
   

value

缓存的名称,在 spring 配置文件中定义,必须指定至少一个

例如: @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}

key

缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

例如: @Cacheable(value=”testcache”,key=”#userName”)

condition

缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

例如: @Cacheable(value=”testcache”,condition=”#userName.length()>2”)

表 3. @CacheEvict 作用和配置方法

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空


@CacheEvict 主要的参数
   

value

缓存的名称,在 spring 配置文件中定义,必须指定至少一个

例如: @CachEvict(value=”mycache”) 或者 @CachEvict(value={”cache1”,”cache2”}

key

缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

例如: @CachEvict(value=”testcache”,key=”#userName”)

condition

缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存

例如: @CachEvict(value=”testcache”, condition=”#userName.length()>2”)

allEntries

是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存

例如: @CachEvict(value=”testcache”,allEntries=true)

beforeInvocation

是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存

例如: @CachEvict(value=”testcache”,beforeInvocation=true)
时间: 2024-10-20 23:29:06

spring 方法级缓存多种实现的相关文章

Spring AOP +EHcache为Service层方法增加缓存

在铁科院做了一个关于医保报销的项目,在这个个系统中大量使用了下拉列表框,系统主要是给机关单位使用而且都是一些干部退休了啥的,年龄都比较大不愿意自己输入东西,因此界面上的很多值都是下拉列表框从数据字典表里面加载出来. 如此以来字典表的数据量变的越来越大,在一个界面上往往需要频繁的与字典表交互,觉的很影响性能于是我们增加了缓存,即为service层中的指定方法缓存功能,具体实现是利用Spring AOP+EHcache来做. 第一次执行某个方法的时候会去数据库里面查询,当第二次执行该方法时就会去从缓

使用Spring提供的缓存抽象机制整合EHCache为项目提供二级缓存

Spring自身并没有实现缓存解决方案,但是对缓存管理功能提供了声明式的支持,能够与多种流行的缓存实现进行集成. Spring Cache是作用在方法上的(不能理解为只注解在方法上),其核心思想是:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值存放在缓存中,等到下次利用同样的参数调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回.所以在使用Spring Cache的时候我们要保证我们的缓存的方法对于相同的方法参数要有相同的返回结果. 1.适合和不适合保存到二级缓存的数

mybatis学习笔记(14)-查询缓存之中的一个级缓存

mybatis学习笔记(14)-查询缓存之中的一个级缓存 mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 本文主要讲mybatis的一级缓存.一级缓存是SqlSession级别的缓存. 查询缓存 mybatis提供查询缓存.用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级缓存是SqlSession级别的缓存.在操作数据库时须要构造sqlSession对象,在对象中有一个数据结构(HashMa

用guava快速打造两级缓存能力

首先,咱们都有一共识,即可以使用缓存来提升系统的访问速度! 现如今,分布式缓存这么强大,所以,大部分时候,我们可能都不会去关注本地缓存了! 而在一起高并发的场景,如果我们一味使用nosql式的缓存,如 redis, 那么也是好的吧! 但是有个问题我们得考虑下: redis 这样的缓存是快,但是它总有自己的瓶颈吧,如果什么东西我们都往里面存储,则在高并发场景下,应用瓶颈将受限于其缓存瓶颈吧! 所以,针对这种问题,在一些场景下,咱们可以使用本地缓存来存储一些数据,从而避免每次都将请求击穿到 redi

Hibernate-二级缓存

与Session相对的是,SessionFactory也提供了相应的缓存机制.SessionFactory缓存可以依据功能和目的的不同而划分为内置缓存和外置缓存. SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的副本,而预定义SQL语句是在 Hibernate初始化阶段根据映射元数据推导出来的.SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义 SQL语句,因此SessionFactory不需要进行内

Java内部类实现伪方法级多线程

最近碰到一个问题,就是用户在填写相关信息提交后,后台需要将一些文件同步到另外一台服务器,而这个时候,由于用的是spring的框架,导致前端页面需要等待文件同步完成,才能弹出提示信息.相信大家在很多时候都会碰到这种问题,比如收发邮件,也会等待邮件发送完成,等等.于是便很自然的想到多开一个线程去处理一些比较耗时的任务.但是java本身只提供类级别的多线程,如下: 继承Thread类 class A extends Thread { public void run() { System.out.pri

mybatis13--2级缓存

验证内置的2级缓存 创建对应的dao public interface StudentDao { /** * 验证mybatis2级缓存! */ Student selectStudentById(Integer sId); } 创建对应的mapper文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3

缓存插件 Spring支持EHCache缓存

Spring仅仅是提供了对缓存的支持,但它并没有任何的缓存功能的实现,spring使用的是第三方的缓存框架来实现缓存的功能.其中,spring对EHCache提供了很好的支持. 在介绍Spring的缓存配置之前,我们先看一下EHCache是如何配置. <?xml version="1.0" encoding="UTF-8" ?> <ehcache> <!-- 定义默认的缓存区,如果在未指定缓存区时,默认使用该缓存区 --> <

Spring AOP + Redis缓存数据库查询

应用场景 我们希望能够将数据库查询结果缓存到Redis中,这样在第二次做同样的查询时便可以直接从redis取结果,从而减少数据库读写次数. 需要解决的问题 操作缓存的代码写在哪?必须要做到与业务逻辑代码完全分离. 如何避免脏读? 从缓存中读出的数据必须与数据库中的数据一致. 如何为一个数据库查询结果生成一个唯一的标识?即通过该标识(Redis中为Key),能唯一确定一个查询结果,同一个查询结果,一定能映射到同一个key.只有这样才能保证缓存内容的正确性 如何序列化查询结果?查询结果可能是单个实体