不管是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); } } }