Spring Data Redis 項目源碼框架分析

fmms 12年前發布 | 68K 次閱讀 Sprin NoSQL數據庫 Redis

redis是由Salvatore Sanfilippo用C語言編寫的一個緩存系統,與memcached相比,提供了更多的處理復雜數據結構的方法;性能也非常的突出。

  由于項目需要,自己簡單地看了下spring新加入的模塊 spring data redis,spring data redis對jedis, jredis, rjc等redis的java客戶端接口進行了進一部的抽象,類似于jdbcTemplate的實現。具體spring配置方式如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans&quot; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
        xmlns:p="http://www.springframework.org/schema/p&quot;
        xmlns:context="http://www.springframework.org/schema/context&quot; 
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"&gt;

<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
    p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"/>
<!-- Configurer that replaces ${...} placeholders with values from a properties file -->
<context:property-placeholder location="classpath:redis.properties"/>

<context:annotation-config />

<context:component-scan base-package="org.springframework.data.redis.samples"/>

<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" 
    p:connection-factory-ref="connectionFactory"/>

</beans></pre>

 connectionFactory功能類似于spring 數據庫連接的datasource,提供對遠程redis server的連接訪問;  redisTemplate類似于SqlMapClientTemplate,提供對數據庫訪問的模板方法。 

 

下面是spring data redis class diagram 404e1c02-5c9b-3939-91fe-281f9b26222f.jpg
結合下面的代碼我們進行分析:

public class Example{
    @autowired
    private RedisTemplate<String,String> template;

public void addLink(String userId, URL url){
    template.opsForList.leftPush(userId, url.toExternalForm);
}

}</pre> spring data redis根據數據的類型進行了接口方法的拆分,如 ValueOperations,ListOperations,SetOperations,ZSetOperations。template調用 opsForList拿到具體的對哪種數據結構進行操作的對象,進而調用相應的操作方法。DefaultListOperations等對象使用回調函數的方法向redis server進行請求。 

   public Long leftPush(K key, V value) {
        final byte[] rawKey = rawKey(key);
        final byte[] rawValue = rawValue(value);
        return execute(new RedisCallback<Long>() {

        public Long doInRedis(RedisConnection connection) {
            return connection.lPush(rawKey, rawValue);
        }
    }, true);
}</pre> 在RedisTemplate中,有一個重要的方法execute對connection進行預處理,包括是否使用pipeline,是否expose(暴露)connection等,對server進行請求后的返回結果進行后續的處理等。  

   /**

 * Executes the given action object within a connection that can be exposed or not. Additionally, the connection
 * can be pipelined. Note the results of the pipeline are discarded (making it suitable for write-only scenarios).
 * 
 * @param <T> return type
 * @param action callback object to execute
 * @param exposeConnection whether to enforce exposure of the native Redis Connection to callback code
 * @param pipeline whether to pipeline or not the connection for the execution 
 * @return object returned by the action
 */
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
    Assert.notNull(action, "Callback object must not be null");

    RedisConnectionFactory factory = getConnectionFactory();
    //由spring中配置的JedisConnectionFactory創建連接 
    RedisConnection conn = RedisConnectionUtils.getConnection(factory);

    boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
    preProcessConnection(conn, existingConnection);

    boolean pipelineStatus = conn.isPipelined();//判斷是否打開pipeline 
    if (pipeline && !pipelineStatus) {
        conn.openPipeline();
    }

    try {
        RedisConnection connToExpose = (exposeConnection ? conn : createRedisConnectionProxy(conn));
        T result = action.doInRedis(connToExpose);
        // TODO: any other connection processing?
        // 對后續結果進行處理,但postProcessResult還是直接返回result的,不知為何? 
        return postProcessResult(result, conn, existingConnection);
    } finally {
        try {
            if (pipeline && !pipelineStatus) {
                conn.closePipeline();
            }
        } finally {
            RedisConnectionUtils.releaseConnection(conn, factory);
        }
    }
}</pre> 

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!