Spring-RedisTemplate原理


    不管是mysql數據庫、redis數據庫、activeMq,咱們都須要建立客戶端鏈接、根據業務邏輯進行增刪改查、關閉客戶端鏈接等操做。在Spring中爲例簡化這一系列的操做。提供了模板類。java

    將數據訪問中的固定和變化部分分開,相同的數據訪問流程固話到模板類中變化的部分經過回調接口開放出來,用於具體定義數據訪問和結果返回的操做,同時保證模板類是線程安全的,以便多個數據訪問線程共享同一個模板實例。mysql

 


在S平日那個中有不少模板類,好比HibernateTemplate、JdbcTemplate、RedisTemplate等等。本文將以RedisTemplate、JdbcTemplate爲例,講解建立鏈接、執行操做、釋放鏈接這一系列操做;redis

1、RedisTemplatespring

對於單個使用線程池的jedis操做步驟請看java操做redis的章節,對於spring整合redis也請看前面章節。本章主要講解源碼!sql

List<String> list=new ArrayList<String>();
list.add("value1");
list.add("value2");
ListOperations<String, String> listOperations=redisTemplate.opsForList();
listOperations.rightPushAll("listCol", list);


上面的代碼是一段向隊列中添加List的操做。咱們以此爲例講解:數據庫


1)首先涉及到的類有:安全

DefaultListOperation //主要用於封裝對List的操做,主要是調用RedisTemplate中的execute方法ide

StringRedisSerializer //key的序列化和反序列化的工具類函數

JdkSerializationRedisSerializer //value的序列化和反序列化的工具類工具

RedisCallback //回調接口,具體定義數據訪問和結果返回的操做

RedisTemplate //redis操做模板類,用於封裝redis的操做數據流程

RedisConnectionUtils //用於管理redis客戶端鏈接

TransactionSynchronizationManager //線程同步管理

JedisConnectionFactory //建立Jedis的工廠類

Jedis //redis的客戶端鏈接對象

JedisConnection //用於封裝真正的Jedis鏈接對象


2)分析上面代碼的源碼

redisTemplate.opsForList();//會建立DefaultListOperation 對象,該對象中封裝了RedisTemplate。

listOperations.rightPushAll("listCol", list);//具體方法代碼以下圖

/*****
**DefaultListOperation類中主要的調用
***主要成員變量:RedisTemplate
******/
@Override
public Long rightPushAll(K key, Collection<V> values) {

//序列化對象key、value
//調用RedisTemplate的keySerializer、valueSerializer的serialize()
final byte[] rawKey = rawKey(key);
final byte[][] rawValues = rawValues(values);

//調用RedisTemplate的方法execute,實現對Redis操做
return execute(new RedisCallback<Long>(){ 

    //實現回調接口
    public Long doInRedis(RedisConnection connection) {
        return connection.rPush(rawKey, rawValues);
    }
  }, true); //參數exposeConnection(公開鏈接):true
}


@SuppressWarnings("unchecked")
byte[] rawKey(Object key) {
    Assert.notNull(key, "non null key required");
    if (keySerializer() == null && key instanceof byte[]) {
        return (byte[]) key;
    }
    //實際調用RedisTemplate來序列化key
    return keySerializer().serialize(key);
}

//調用RedisTemplate的方法
RedisSerializer keySerializer() {
    return template.getKeySerializer();
}

//調用RedisTemplate的方法
<T> T execute(RedisCallback<T> callback, boolean b) {
    return template.execute(callback, b);
}


/*****
**RedisTemplate類中主要的調用
***主要成員變量:JedisConnectionFactory
******/
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {

    //redis鏈接工廠,用於建立、關閉redis鏈接
    RedisConnectionFactory factory = getConnectionFactory();
   
    //內部封裝真正的redis鏈接,用於實現各類操做
    RedisConnection conn = null;
    
    try {
    
        //默認不啓動事務,redis鏈接是經過RedisConnectionUtils得到的
        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();
        }
        
        //是否爲jedisConnection,建立動態代理對象(jdk動態代理技術)
        RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
       
        //調用回調函數,執行數據庫操做,之部分是動態的,能夠由用戶本身指定操做
        T result = action.doInRedis(connToExpose);
        
        // close pipeline
        if (pipeline && !pipelineStatus) {
            connToUse.closePipeline();
        }
        
        // TODO: any other connection processing?
        return postProce***esult(result, connToUse, existingConnection);
    
    } finally {
    
        //非事務操做,釋放鏈接
        if (!enableTransactionSupport) {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }
    }
}
相關文章
相關標籤/搜索