无论是mysql数据库、redis数据库、activeMq,我们都需要创建客户端连接、根据业务逻辑进行增删改查、关闭客户端连接等操作。在Spring中为例简化这一系列的操作。提供了模板类。

将数据访问中的固定和变化部分分开,将相同的数据访问流程固话到模板类中,变化的部分通过回调接口开放出来,用于具体定义数据访问和结果返回的操作,同时保证模板类是线程安全的,以便多个数据访问线程共享同一个模板实例。



在S平日那个中有很多模板类,比如HibernateTemplate、JdbcTemplate、RedisTemplate等等。本文将以RedisTemplate、JdbcTemplate为例,讲解创建连接、执行操作、释放连接这一系列操作;

一、RedisTemplate

对于单个使用线程池的jedis操作步骤请看java操作redis的章节,对于spring整合redis也请看前面章节。本章主要讲解源码!

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


上面的代码是一段向队列中添加List的操作。我们以此为例讲解:


1)首先涉及到的类有:

DefaultListOperation //主要用于封装对List的操作,主要是调用RedisTemplate中的execute方法

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******/@OverridepublicLongrightPushAll(Kkey,Collection<V>values){//序列化对象key、value//调用RedisTemplate的keySerializer、valueSerializer的serialize()finalbyte[]rawKey=rawKey(key);finalbyte[][]rawValues=rawValues(values);//调用RedisTemplate的方法execute,实现对Redis操作returnexecute(newRedisCallback<Long>(){//实现回调接口publicLongdoInRedis(RedisConnectionconnection){returnconnection.rPush(rawKey,rawValues);}},true);//参数exposeConnection(公开连接):true}@SuppressWarnings("unchecked")byte[]rawKey(Objectkey){Assert.notNull(key,"nonnullkeyrequired");if(keySerializer()==null&&keyinstanceofbyte[]){return(byte[])key;}//实际调用RedisTemplate来序列化keyreturnkeySerializer().serialize(key);}//调用RedisTemplate的方法RedisSerializerkeySerializer(){returntemplate.getKeySerializer();}//调用RedisTemplate的方法<T>Texecute(RedisCallback<T>callback,booleanb){returntemplate.execute(callback,b);}/*******RedisTemplate类中主要的调用***主要成员变量:JedisConnectionFactory******/public<T>Texecute(RedisCallback<T>action,booleanexposeConnection,booleanpipeline){//redis连接工厂,用于创建、关闭redis连接RedisConnectionFactoryfactory=getConnectionFactory();//内部封装真正的redis连接,用于实现各种操作RedisConnectionconn=null;try{//默认不启动事务,redis连接是通过RedisConnectionUtils获得的if(enableTransactionSupport){//onlybindresourcesincaseofpotentialtransactionsynchronizationconn=RedisConnectionUtils.bindConnection(factory,enableTransactionSupport);}else{conn=RedisConnectionUtils.getConnection(factory);}//是否和当事务同步管理器程绑定booleanexistingConnection=TransactionSynchronizationManager.hasResource(factory);//RedisConnectionconnToUse=preProcessConnection(conn,existingConnection);//管道状态:用于批量操作booleanpipelineStatus=connToUse.isPipelined();if(pipeline&&!pipelineStatus){connToUse.openPipeline();}//是否为jedisConnection,创建动态代理对象(jdk动态代理技术)RedisConnectionconnToExpose=(exposeConnection?connToUse:createRedisConnectionProxy(connToUse));//调用回调函数,执行数据库操作,之部分是动态的,可以由用户自己指定操作Tresult=action.doInRedis(connToExpose);//closepipelineif(pipeline&&!pipelineStatus){connToUse.closePipeline();}//TODO:anyotherconnectionprocessing?returnpostProce***esult(result,connToUse,existingConnection);}finally{//非事务操作,释放连接if(!enableTransactionSupport){RedisConnectionUtils.releaseConnection(conn,factory);}}}