关于缓存java
缓存是实际工做中很是经常使用的一种提升性能的方法。而在java中,所谓缓存,就是将程序或系统常常要调用的对象存在内存中,再次调用时能够快速从内存中获取对象,没必要再去建立新的重复的实例。这样作能够减小系统开销,提升系统效率。git
在增删改查中,数据库查询占据了数据库操做的80%以上,而很是频繁的磁盘I/O读取操做,会致使数据库性能极度低下。而数据库的重要性就不言而喻了:redis
在系统架构的不一样层级之间,为了加快访问速度,均可以存在缓存spring
spring cache特性与缺憾数据库
如今市场上主流的缓存框架有ehcache、redis、memcached。spring cache能够经过简单的配置就能够搭配使用起来。其中使用注解方式是最简单的。apache
Cache注解缓存
从以上的注解中能够看出,虽然使用注解的确方便,可是缺乏灵活的缓存策略,微信
缓存策略:架构
TTL(Time To Live ) 存活期,即从缓存中建立时间点开始直到它到期的一个时间段(无论在这个时间段内有没有访问都将过时)mvc
TTI(Time To Idle) 空闲期,即一个数据多久没被访问将从缓存中移除的时间
项目中可能有不少缓存的TTL不相同,这时候就须要编码式使用编写缓存。
条件缓存
根据运行流程,以下@Cacheable将在执行方法以前( #result还拿不到返回值)判断condition,若是返回true,则查缓存;
@Cacheable(value = "user", key = "#id", condition = "#id lt 10") public User conditionFindById(final Long id)
以下@CachePut将在执行完方法后(#result就能拿到返回值了)判断condition,若是返回true,则放入缓存
@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'") public User conditionSave(final User user)
以下@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,若是返回false,则放入缓存;(即跟condition相反)
@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'") public User conditionSave2(final User user)
以下@CacheEvict, beforeInvocation=false表示在方法执行以后调用(#result能拿到返回值了);且判断condition,若是返回true,则移除缓存;
@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'") public User conditionDelete(final User user)
@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; }
配置ehcache与redis
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>${ehcache.version}</version> </dependency>
<!-- Spring提供的基于的Ehcache实现的缓存管理器 --> <!-- 若是有多个ehcacheManager要在bean加上p:shared="true" --> <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:xml/ehcache.xml"/> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcacheManager"/> <property name="transactionAware" value="true"/> </bean> <!-- cache注解,和spring-redis.xml中的只能使用一个 --> <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.8.1.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
<!-- 注意须要添加Spring Data Redis等jar包 --> <description>redis配置</description> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.pool.maxIdle}"/> <property name="maxTotal" value="${redis.pool.maxActive}"/> <property name="maxWaitMillis" value="${redis.pool.maxWait}"/> <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/> <property name="testOnReturn" value="${redis.pool.testOnReturn}"/> </bean> <!-- JedisConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.master.ip}"/> <property name="port" value="${redis.master.port}"/> <property name="poolConfig" ref="jedisPoolConfig"/> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connectionFactory-ref="jedisConnectionFactory"> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean> <!--spring cache--> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:redisOperations-ref="redisTemplate"> <!-- 默认缓存10分钟 --> <property name="defaultExpiration" value="600"/> <property name="usePrefix" value="true"/> <!-- cacheName 缓存超时配置,半小时,一小时,一天 --> <property name="expires"> <map key-type="java.lang.String" value-type="java.lang.Long"> <entry key="halfHour" value="1800"/> <entry key="hour" value="3600"/> <entry key="oneDay" value="86400"/> <!-- shiro cache keys --> <entry key="authorizationCache" value="1800"/> <entry key="authenticationCache" value="1800"/> <entry key="activeSessionCache" value="1800"/> </map> </property> </bean> <!-- cache注解,和spring-ehcache.xml中的只能使用一个 --> <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
项目中注解缓存只能配置一个,因此能够经过如下引入哪一个配置文件来决定使用哪一个缓存。
<import resource="classpath:spring/spring-ehcache.xml"/> <!-- <import resource="classpath:spring/spring-redis.xml"/>-->
固然,能够经过其余配置搭配使用两个缓存机制。好比ecache作一级缓存,redis作二级缓存。
更加详细的使用与配置,能够参考项目中spring-shiro-training中有关spring cache的配置。
写在最后
欢迎关注个人微信公众号java思惟导图,下载导图源文件,以及更多java思惟导图与项目资料供你学习,带你走进记忆脑图的世界。
关注公众号并回复“思惟导图”即刻下载源xmind导图。
上篇文章阅读