redisTemplate類學習及理解
List<Object> list = masterRedisTemplate.executePipelined((RedisCallback<Long>) connection -> { StringRedisConnection redisConn = (StringRedisConnection) connection; Integer expireTime = XXX; redisConn.expire(XXX); RedisUtil.addSameScoreTail(XXXX); return null; });
redisTemplate簡化Redis資料訪問程式碼的Helper類。在給定物件和中的基礎二進位制資料之間執行自動序列化/反序列化。中心方法是execute,支援實現X介面的Redis訪問程式碼,它提供了RedisConnection處理,使得RedisCallback實現和呼叫程式碼都不需要顯式關心檢索/關閉Redis連線,或處理連線生命週期異常。對於典型的單步動作,有各種方便的方法。一旦配置好,這個類就是執行緒安全的。這是Redis支援的核心類。
1 public class RedisTemplate<K, V> extendsRedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
介面 RedisAccessor:,該介面指定了一組基本的Redis操作,由RedisTemplate實現。不經常使用,但對於可擴充套件性和可測試性來說是一個有用的選項(因為它很容易被模仿或存根)。
2 private boolean enableTransactionSupport = false;
true:開啟之後則開啟事務;3 private boolean exposeConnection = false;
曝光連結@Override
public List<Object> executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) {return execute((RedisCallback<List<Object>>) connection -> {
首先開通連線
connection.openPipeline();標誌連線是否關閉 這裡有個問題時下面這個true設定是為什麼 後續是不是會改為false,要不導致記憶體洩漏了。 :::在deserialize這個方法裡傳的closePipline引數可以把關閉連線傳遞過去。
boolean pipelinedClosed = false;
try {其次處理傳來的action的doInRedis方法。 這個doinredis方法就是本文第一個程式碼塊的程式碼,即當前方法入參傳過來的程式碼塊的內容。
Object result = action.doInRedis(connection);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;最後呼叫deserializeMixedResults,把返回結果帶入到execute去繼續執行。 這個是一個反序列化相關的方法。
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
}
StringRedisConnection redisConn = (StringRedisConnection) connection; 在呼叫executePipelined前,可以用來操作資料。
這個execute是executePipelined處理的具體實現。
@Nullable public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) { Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it"); Assert.notNull(action, "Callback object must not be null"); RedisConnectionFactory factory = getRequiredConnectionFactory(); RedisConnection conn = null; try { if (enableTransactionSupport) { // only bind resources in case of potential transaction synchronization conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport); } else { conn = RedisConnectionUtils.getConnection(factory); } boolean existingConnection = TransactionSynchronizationManager.hasResource(factory); RedisConnection connToUse = preProcessConnection(conn, existingConnection); boolean pipelineStatus = connToUse.isPipelined(); if (pipeline && !pipelineStatus) { connToUse.openPipeline(); } RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse)); T result = action.doInRedis(connToExpose);
具體執行的也是本文最上面的程式碼塊裡的方法。
// close pipeline if (pipeline && !pipelineStatus) { connToUse.closePipeline(); } // TODO: any other connection processing? return postProcessResult(result, connToUse, existingConnection); } finally { RedisConnectionUtils.releaseConnection(conn, factory); } }
redisTemplate其他方法
delete
@Override public Boolean delete(K key) { key轉成序列化的 byte[] rawKey = rawKey(key); 呼叫execute方法 Long result = execute(connection -> connection.del(rawKey), true); 判斷返回值 return result != null && result.intValue() == 1; }
這個execute也是呼叫的上面的execute方法,獲取到連線之後,執行程式碼塊裡的del命令。
expire
加失效時間
@Override public Boolean expire(K key, final long timeout, final TimeUnit unit) { 序列化 byte[] rawKey = rawKey(key);
計算超時時間 long rawTimeout = TimeoutUtils.toMillis(timeout, unit); return execute(connection -> { try {
呼叫 return connection.pExpire(rawKey, rawTimeout); } catch (Exception e) { // Driver may not support pExpire or we may be running on Redis 2.4 return connection.expire(rawKey, TimeoutUtils.toSeconds(timeout, unit)); } }, true); }
計算好了之後 同樣也是通過execute方法,獲取連線後執行。
opsForHash
RedisTemplate.opsForHash().put/get/delete等等
HashOperations
@Override public <HK, HV> HashOperations<K, HK, HV> opsForHash() { return new DefaultHashOperations<>(this); } 這個方法實現了hashOperations介面 class DefaultHashOperations<K, HK, HV> extends AbstractOperations<K, Object> implements HashOperations<K, HK, HV> { @SuppressWarnings("unchecked") DefaultHashOperations(RedisTemplate<K, ?> template) { super((RedisTemplate<K, Object>) template); } }
@Override public void put(K key, HK hashKey, HV value) { byte[] rawKey = rawKey(key); byte[] rawHashKey = rawHashKey(hashKey); byte[] rawHashValue = rawHashValue(value); execute(connection -> {
這裡通過execute方法,把這個程式碼塊執行。具體的引數是key ,hashkey,value 的三個序列化之後的引數。 connection.hSet(rawKey, rawHashKey, rawHashValue); return null; }, true); }
OpsForSet()
RedisTemplate.opsForSet().add(key, value); public Long add(K key, V... values) { 序列化 byte[] rawKey = rawKey(key);
values是多組二進位制 byte[][] rawValues = rawValues((Object[]) values);
return execute(connection -> connection.sAdd(rawKey, rawValues), true); }
大致就是相關的用法,不通的資料結構 ,有自己特有的Operations方法,可以具體檢視。