spring(13)缓存数据
way1)注解驱动的缓存;way2)XML 声明的缓存
2.1)在往bean上添加缓存注解的时候,必须要启用 spring 对注解驱动缓存的支持。如果使用 java配置的话,可以在其中的一个配置类上添加 @EnableCaching注解,这样就能启用注解驱动缓存了。(干货——@EnableCaching注解的作用)2.2)java配置启用注解驱动的缓存,代码如下所示:@Configuration @EnableCaching // 启用缓存 public class CachingConfig {@Beanpublic CacheManager cacheManager() { // 声明缓存管理器return new ConcurrentMapCacheManager();} }
2.3)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" /> </beans>
对以上代码的分析(Analysis):
A1)@EnableCaching and <cache:annotation-driven> 的工作方式是相同的;他们都会创建一个切面并触发 spring 缓存注解的切点;A2) 根据所使用的 注解以及缓存的状态,这个切面会从缓存中获取数据,并将数据添加到缓存中或者从缓存中移除这个值;A3)以上的代码还声明了一个 缓存管理器的bean;(ConcurrentMapCacheManager)
- SimpleCacheManager
- NoOpCacheManager
- ConcurrentMapCacheManager
- CompositeCacheManager
- EhCacheCacheManager
- RedisCacheManager (from Spring Data Redis)
- GemfireCacheManager (from Spring Data GemFire)
@Configuration
@EnableCaching // 启用缓存
public class CacheConfig {/** @Bean public CacheManager cacheManager() { // 声明缓存管理器 return new* ConcurrentMapCacheManager(); }*/@Beanpublic EhCacheCacheManager cacheManager(CacheManager cm) {return new EhCacheCacheManager(cm);}@Bean public EhCacheManagerFactoryBean ehcache() { EhCacheManagerFactoryBean cacheFactory = new EhCacheManagerFactoryBean();cacheFactory.setConfigLocation(new ClassPathResource("com/spring/spittr/cache/ehcache.xml"));return cacheFactory; }
}
3.1)在创建 EhCacheManagerFactoryBean,的过程中,需要告诉它 EhCache 配置文件在什么地方;3.2)在这里,通过调用 setConfigLocation()方法,传入 ClassPathResource,用来指明Ehcache XML 配置文件相对于根路径的位置;(参见上一小节的代码)3.3)下面是一个 ehcache.xml 文件的实例<ehcache><cache name="spitterCache"maxBytesLocalHeap="50m"timeToLiveSeconds="100"></cache> </ehcache>
@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
@Bean
public JedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory =
new JedisConnectionFactory();
jedisConnectionFactory.afterPropertiesSet();
return jedisConnectionFactory;
}
@Bean
public RedisTemplate<String, String> redisTemplate(
RedisConnectionFactory redisCF) {
RedisTemplate<String, String> redisTemplate =
new RedisTemplate<String, String>();
redisTemplate.setConnectionFactory(redisCF);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
@Bean
public CacheManager cacheManager(net.sf.ehcache.CacheManager cm,javax.cache.CacheManager jcm) {CompositeCacheManager cacheManager = new CompositeCacheManager();List<CacheManager> managers = new ArrayList<CacheManager>();managers.add(new JCacheCacheManager(jcm));managers.add(new EhCacheCacheManager(cm))managers.add(new RedisCacheManager(redisTemplate()));cacheManager.setCacheManagers(managers);return cacheManager;
}
d1)@Cacheable:首先在缓存中查找条目,如果找到了匹配的条目,那么就不会对方法进行调用了;如果没有找到匹配条目,方法会被调用并且返回值要放到缓存之中;d2)@CachePut:并不会在缓存中检查匹配的值,目标方法总是会被调用,并将返回值添加到缓存中;(干货——@Cacheable 和 @CachePut 注解的作用)
@Cacheable("spittleCache")
public Spittle findOne(long id) {try {return jdbcTemplate.queryForObject(SELECT_SPITTLE_BY_ID,new SpittleRowMapper(),id);} catch (EmptyResultDataAccessException e) {return null;}
}
A1)当findOne()方法被调用时,缓存切面会拦截调用并在缓存中查找之前以名 spittleCache 存储的返回值;A2)缓存key 是传递到 findOne()方法中的id 参数;
A2.1)如果找到这个值的话:那么方法不会再被调用;A2.2)如果没有找到这个值的话:那么就会调用这个方法,并将返回值放到缓存中,为下一次调用 findOne()方法做准备;
4.1)problem:@Cacheable的缓存作用只限于 JdbcSpittleRepository这个实现类中,SpittleRepository的其他实现并没有缓存功能,除非也为其添加上 @Cacheable注解;4.2)solution:可以考虑将注解添加到 SpittleRepository的方法声明上,而不是放在实现类中(放在 顶层的接口中);(干货——应该将缓存注解Cacheable添加到Repository的接口声明中)public interface SpitterRepository {@CachePut("spitterCache")Spitter save(Spitter spitter);@Cacheable("spitterCache")Spitter findByUsername(String username);@Cacheable("spitterCache")String findPassByUsername(String username); }
@CachePut("spitterCache")
Spittle save(Spittle spittle);
A1)对于save()方法来说,我们需要的键是 所返回的 Spittle对象 的 id属性;A2)表达式 #result 能够得到返回的 Spittle,可以通过将 key 属性设置为 #result.id 来引用id 属性;代码如下;@CachePut(value="spitterCache", key="#result.id") Spittle save(Spittle spittle);
1.1)unless:如果unless属性的 SpEL 表达式的值为 true,那么缓存方法返回的数据就不会放到缓存中;1.2)condition:如果 condition 属性的 SpEL 表达式的值为 false,那么对于这个方法缓存就会被禁用掉;
d1)unless属性:只能阻止将对象放进缓存,但在这个方法调用的时候,依然会去缓存中进行你查找,如果找到了匹配的值,就会返回找到的值;(干货——unless是不准进,但可以出)d2)condition属性:一旦 condition的表达式结果为false,缓存就会被禁用,不进也不出;(干货——condition是不进也不出)
@Cacheable(value="spitterCache"unless="#result.message.contains('NoCache')")
Spittle findOne(long id);
@Cacheable(value="spitterCache"unless="#result.message.contains('NoCache')"condition="#id >= 10")
Spittle findOne(long id);
对以上代码的分析(Analysis):
A1)如果findOne() 调用时,参数值小于10,那么就不会在缓存中进行查找:返回的 Spittle 也不会放入缓存中,就想这个方法没有添加 @Cacheable 注解一样;A2)如上例所示:unless属性 的表达式能够通过 #result 引用返回值;之所以这么做是因为 unless属性 只有在缓存方法有返回值时 才开始发挥作用;A3)如上例所示:condition属性: 肩负着在方法上禁用缓存的任务,因此它不能等到方法返回时再确定是否该关闭缓存。这因为这它的表达式必须要在进入方法前进行计算,所以在condition属性中不能引用 #result 返回值;(干货——这里道出了 unless属性和 condition属性的有一大区别,即unless属性的结果是 对方法调用后的引用,而condition属性的结果是方法调用前的计算结果)
@CacheEvict("spitterCache")
void remove(long spittleId)
A1)与 @Cacheable 和 @CachePut 不同:@CacheEvict 能够应用在 返回值 为 void 的 方法上,而 @Cacheable 和 @CachePut 需要非 void 的返回值;它将会作为放在缓存中的条目,因为 @CacheEvict 只是将条目从 缓存中移除,因此它可以放在任意的 方法上,甚至void 方法上;A2)对以上代码的分析(Analysis):当remove() 调用时,会从 缓存中删除一个条目,被删除条目的key 与传递进来的spittleId 的值要相等;A3)@CacheEvict有多个属性,如下表所示:
public interface SpitterRepository {@CachePut("spitterCache")Spitter save(Spitter spitter);@Cacheable("spitterCache")Spitter findByUsername(String username);String findPassByUsername(String username);int getItemSum(); List<Spitter> findSpitters(int limit, int offset);
}
<?xml version="1.0" encoding="gbk"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="ehcache.xsd"><diskStore path="java.io.tmpdir" /><defaultCache maxElementsInMemory="10000" eternal="false"timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="false" /><cache name="spitterCache" maxElementsInMemory="10000"eternal="false" overflowToDisk="false" timeToIdleSeconds="900"timeToLiveSeconds="1800" memoryStoreEvictionPolicy="LFU" />
</ehcache>
public interface SpitterRepository {@CachePut("spitterCache")Spitter save(Spitter spitter);@Cacheable("spitterCache")Spitter findByUsername(String username);String findPassByUsername(String username);int getItemSum();List<Spitter> findSpitters(int limit, int offset);@CacheEvict("spitterCache") // highlight line.int delete(String username);
}
@Overridepublic int delete(String username) { //defined in SpitterRepositoryImpl.javasql = "delete from t_spitter where username=?";int result = jdbc.update(sql, username);System.out.println("delete result = " + result);return result;}
@RequestMapping(value = "/delete", method = RequestMethod.GET)public String removeSpitter( //defined in SpitterController.java.@RequestParam String username, @RequestParam(name="curpage") String curpage) {spitterRepository.delete(username);return "redirect:/spitter/paging?curpage=" + curpage;}
1.1)why:为什么想要以 XML 的方式声明缓存?1.2)reasons:
reason1)你可能会觉得 在 自己的源码中添加 spring 的注解有点不太方便;reason2)你需要在没有源码的bean上应用 缓存功能;
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
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">
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
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">
<aop:config>
<aop:advisor advice-ref="cacheAdvice"
<cache:annotation-driven> Enables annotation-driven caching. Equivalent to
@EnableCaching in Java configuration.
<cache:advice> Defines caching advice. Paired with <aop:advisor> to
apply advice to a pointcut.
<cache:caching> Defines a specific set of caching rules within the caching
advice.
<cache:cacheable> Designates a method as being cacheable. Equivalent to the
@Cacheable annotation.
<cache:cache-put> Designates a method as populating (but not considering) the
cache. Equivalent to the @CachePut annotation.
<cache:cache-evict> Designates a method as evicting one or more entries from the
cache. Equivalent to the @CacheEvict annotation.
Bind cache advice
to a pointcut
pointcut=
"execution(* com.habuma.spittr.db.SpittleRepository.*(..))"/>
</aop:config>
<cache:advice id="cacheAdvice">
<cache:caching>
<cache:cacheable
cache="spittleCache"
method="findRecent" />
<cache:cacheable
cache="spittleCache" method="findOne" />
<cache:cacheable
cache="spittleCache"
method="findBySpitterId" />
<cache:cache-put
cache="spittleCache"
method="save"
key="#result.id" />
<cache:cache-evict
cache="spittleCache"
method="remove" />
</cache:caching>
</cache:advice>
<bean id="cacheManager" class=
"org.springframework.cache.concurrent.ConcurrentMapCacheManager"
/>
</beans>
spring(13)缓存数据相关推荐
- spring + redis 实现数据的缓存
1.实现目标 通过redis缓存数据.(目的不是加快查询的速度,而是减少数据库的负担) 2.所需jar包 注意:jdies和commons-pool两个jar的版本是有对应关系的,注意引入jar包是要 ...
- spring boot 缓存_Spring Boot 集成 Redis 实现数据缓存
Spring Boot 集成 Redis 实现数据缓存,只要添加一些注解方法,就可以动态的去操作缓存了,减少代码的操作. 在这个例子中我使用的是 Redis,其实缓存类型还有很多,例如 Ecache. ...
- Spring认证指南:了解如何在 GemFire 中缓存数据
原标题:使用 Pivotal GemFire 缓存数据(Spring中国教育管理中心) 本指南演练了使用阿帕奇大地的数据管理系统,用于缓存应用程序代码中的某些调用. 有关Apache Geode概念和 ...
- spring boot使用redis缓存数据与自动清除
在spring boot项目中使用缓存很方便,有如下两种使用场景: 直接操作RedisTemplate缓存数据 在方法上加@Cacheable注解来缓存数据 方法1适用于缓存session.token ...
- Spring指南之使用Spring缓存数据(Spring Framework官方文档之缓存抽象详解)
1.请参见官方文档Spring指南之使用 Spring 缓存数据 2.请参见Spring官方文档之缓存抽象 3.参见github代码 文章目录 一.简介 二.你将创造什么(What You Will ...
- 注释驱动的 Spring cache 缓存介绍--转载
概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...
- Spring+EhCache缓存实例(详细讲解+源码下载)
转载注明出处http://blog.csdn.net/u013142781 一.ehcahe的介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的 ...
- 注解驱动的 Spring cache 缓存介绍
概述 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术 ...
- 注释驱动的 Spring cache 缓存介绍
概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...
最新文章
- 受损骨骼可能在类似地球的重力条件下更快愈合
- 使用开源CRM进行客户关系管理(2)
- 图片异步上传,使用ajax上传图片
- 弄明白python reduce 函数
- 数据结构-堆 Java实现
- mysql oracle 锁机制_Mysql锁机制
- (53)FPGA基础编码D触发器(二)
- 1.1 OC类的认识
- 素数快速求法 -- 筛法求素数
- 关于给电鼓音源增加鼓盘或者DIY鼓盘(DIY镲片)的方法
- 7z001怎么解压在安卓手机上面_手机存储告急怎么办?这份安卓清理指南请收好...
- Hadoop3.x完全分布式运行模式配置
- 力天创见客流计数方案
- Chromium的GPU进程启动过程分析
- 基于springboot框架的快递代取跑腿服务系统
- 腾然教育官网重新升级改版,2022年涅槃重生,王者归来
- mysql 如何把date转换数字_请教:mysql中,如何将date字段转换为int字段?
- 挂微群发软件需要什么服务器信,用云服务器挂群发软件
- python编程计算_python编程 小小计算器
- ehcache 默认大小_ehcache基本原理