Spring思维导图,让Spring不再难懂(cache篇)

关于缓存

缓存是实际工作中非常常用的一种提高性能的方法。而在java中,所谓缓存,就是将程序或系统经常要调用的对象存在内存中,再次调用时可以快速从内存中获取对象,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

在增删改查中,数据库查询占据了数据库操作的80%以上,而非常频繁的磁盘I/O读取操作,会导致数据库性能极度低下。而数据库的重要性就不言而喻了:

  • 数据库通常是企业应用系统最核心的部分
  • 数据库保存的数据量通常非常庞大
  • 数据库查询操作通常很频繁,有时还很复杂

在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存

Spring思维导图,让Spring不再难懂(cache篇)

spring cache特性与缺憾

现在市场上主流的缓存框架有ehcache、redis、memcached。spring cache可以通过简单的配置就可以搭配使用起来。其中使用注解方式是最简单的。

Spring思维导图,让Spring不再难懂(cache篇)

Cache注解

Spring思维导图,让Spring不再难懂(cache篇)

从以上的注解中可以看出,虽然使用注解的确方便,但是缺少灵活的缓存策略,

缓存策略:

  • TTL(Time To Live ) 存活期,即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期)
  • TTI(Time To Idle) 空闲期,即一个数据多久没被访问将从缓存中移除的时间

项目中可能有很多缓存的TTL不相同,这时候就需要编码式使用编写缓存。

条件缓存

根据运行流程,如下@Cacheable将在执行方法之前( #result还拿不到返回值)判断condition,如果返回true,则查缓存;

<code>@Cacheable(value="user",key="#id",condition="#idlt10")
publicUserconditionFindById(finalLongid)
/<code>

如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断condition,如果返回true,则放入缓存

<code>@CachePut(value="user",key="#id",condition="#result.usernamene'zhang'")
publicUserconditionSave(finalUseruser)
/<code>

如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,如果返回false,则放入缓存;(即跟condition相反)

<code>@CachePut(value="user",key="#user.id",unless="#result.usernameeq'zhang'")
publicUserconditionSave2(finalUseruser)
/<code>

如下@CacheEvict, beforeInvocation=false表示在方法执行之后调用(#result能拿到返回值了);且判断condition,如果返回true,则移除缓存;

<code>@CacheEvict(value="user",key="#user.id",beforeInvocation=false,condition="#result.usernamene'zhang'")
publicUserconditionDelete(finalUseruser)

/<code>
  • 小试牛刀,综合运用:
<code>    @CachePut(value = "user", key = "#user.id")
public User save(User user) {
users.add(user);
return user;
}

@CachePut(value = "user", key = "#user.id")
public User update(User user) {
users.remove(user);
users.add(user);
return user;
}

@CacheEvict(value = "user", key = "#user.id")
public User delete(User user) {
users.remove(user);
return user;
}

@CacheEvict(value = "user", allEntries = true)
public void deleteAll() {
users.clear();
}

@Cacheable(value = "user", key = "#id")
public User findById(final Long id) {
System.out.println("cache miss, invoke find by id, id:" + id);
for (User user : users) {
if (user.getId().equals(id)) {
return user;
}
}
return null;
}
/<code>

配置ehcache与redis

  • spring cache集成ehcache,spring-ehcache.xml主要内容:
<code><dependency>
\t<groupid>net.sf.ehcache/<groupid>
\t<artifactid>ehcache-core/<artifactid>
\t<version>${ehcache.version}/<version>
/<dependency>
/<code>
<code>


<bean>
<property>
/<bean>

<bean>
<property>
<property>
/<bean>


<annotation-driven>
/<code>
  • spring cache集成redis,spring-redis.xml主要内容:
<code><dependency>
\t<groupid>org.springframework.data/<groupid>
\t<artifactid>spring-data-redis/<artifactid>
\t<version>1.8.1.RELEASE/<version>
/<dependency>
<dependency>
\t<groupid>org.apache.commons/<groupid>
\t<artifactid>commons-pool2/<artifactid>
\t<version>2.4.2/<version>
/<dependency>
<dependency>
\t<groupid>redis.clients/<groupid>
\t<artifactid>jedis/<artifactid>
\t<version>2.9.0/<version>
/<dependency>
/<code>
<code>
<description>redis配置/<description>

<bean>
\t<property>
\t<property>
\t<property>
\t<property>
\t<property>
/<bean>


<bean>
\t<property>
\t<property>
\t<property>
/<bean>

<bean>\t p:connectionFactory-ref="jedisConnectionFactory">
\t<property>
\t\t<bean>
\t/<property>
\t<property>
\t\t<bean>
\t/<property>
\t<property>
\t\t<bean>
\t/<property>
\t<property>
\t\t<bean>
\t/<property>
/<bean>


<bean>\t c:redisOperations-ref="redisTemplate">
\t
\t<property>
\t<property>
\t
\t<property>
\t\t

\t\t\t<entry>
\t\t\t<entry>
\t\t\t<entry>
\t\t\t
\t\t\t<entry>
\t\t\t<entry>
\t\t\t<entry>
\t\t

\t/<property>
/<bean>

<annotation-driven>

/<code>

项目中注解缓存只能配置一个,所以可以通过以下引入哪个配置文件来决定使用哪个缓存。

<code><import>

/<code>

当然,可以通过其他配置搭配使用两个缓存机制。比如ecache做一级缓存,redis做二级缓存。

Spring思维导图,让Spring不再难懂(cache篇)

更加详细的使用与配置,可以参考项目中spring-shiro-training中有关spring cache的配置。

  • https://git.oschina.net/wangzhixuan/spring-shiro-training.git

写在最后,希望对在java开发路上的你,有些帮助!

码农三哥,一名普通程序员,会点java软件开发,对AI人工智能有点兴趣,后续会每日分享些关于互联网技术方面的文章,感兴趣的朋友可以关注我,一起交流学习。

想转型或刚步入程序员Java开发的朋友,有问题可以留言或私信我。

再次感谢你的阅读!


分享到:


相關文章: