歡迎您光臨本站 註冊首頁

Spring cache整合redis代碼實例

←手機掃碼閱讀     e36605 @ 2020-04-29 , reply:0

Spring-Cache是Spring3.1引入的基於註解的緩存技術,本質上它並不是一個具體的緩存實現,而是一個對緩存使用的抽象,通過Spring AOP技術,在原有的代碼上添加少量的註解來實現將這個方法轉成緩存方法的效果。

本來想來個分析源碼,奈何水平有限,先從實戰搞起。

先引入依賴:

org.springframework.bootspring-boot-starter-data-redis2.1.6.RELEASEredis.clientsjedis2.9.3



redis配置:

server: port: 8000 spring: redis: host: 23.95.x.x port: 6379 timeout: 20s database: 0 jedis: pool: max-active: 5 max-idle: 3 max-wait: 5s password: testtest

配置類:

package me.yanand.config; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; @Configuration @EnableCaching public class RedisConfig{ private Duration timeOut = Duration.ofMinutes(30); @Bean public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() //設置緩存超時時間 30分鐘 .entryTtl(timeOut) //設置key序列化方式 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) //設置value序列化方式 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .disableCachingNullValues(); return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).transactionAware().build(); } }

主要看@EnableCaching註解,這個註解引入了@Import(CachingConfigurationSelector.class),通過CachingConfigurationSelector把代理創建類、CacheInterceptor、CacheOperationSource、BeanFactoryCacheOperationSourceAdvisor注入到容器,spring通過CacheInterceptor攔截器攔截相關帶有@Cacheable、@CacheEvict、@CachePut註解的方法並執行相關緩存操作。

CacheInterceptor相關源碼:

@Nullable private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) { if (contexts.isSynchronized()) { CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next(); //滿足條件執行 if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) { Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT); Cache cache = context.getCaches().iterator().next(); try { //這裡主要看RedisCache的get方法 return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker)))); } catch (Cache.ValueRetrievalException ex) { // The invoker wraps any Throwable in a ThrowableWrapper instance so we // can just make sure that one bubbles up the stack. throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause(); } } else { //不滿足直接執行相關方法 return invokeOperation(invoker); } } ...省略 }

RedisCache相關代碼:

public synchronized

T get(Object key, CallablevalueLoader) { ValueWrapper result = get(key); //緩存中有值則返回 if (result != null) { return (T) result.get(); } //緩存中不存在則執行相關方法 T value = valueFromLoader(key, valueLoader); put(key, value); return value; }

註解使用:

package me.yanand.dao; import me.yanand.pojo.User; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; @Component public class UserDao { @Cacheable(cacheNames = "users",key = "#root.targetClass+#name", unless = "#result eq null") public User getUser(String name){ return new User("張三",30); } @CacheEvict(cacheNames = "users", key = "#root.targetClass+#name") public void delUser(String name){ } }

測試:

通過postman觸發相關方法,現在我們連上redis查看緩存寫入情況

這裡我們看到key已經寫入,過期時間也存在

現在我們刪除緩存

[e36605 ] Spring cache整合redis代碼實例已經有265次圍觀

http://coctec.com/docs/java/show-post-232087.html