我们首先来看下面一段代码,这段代码是我们使用Jedis 封装服务的一个实现:
- @服务
- 公开课 JedisSpringDemo {
- @Resource (name = “shardedJedisPool” )
- 私人 ShardedJedisPool shardedJedisPool;
- public String set(String key,String value){
- ShardedJedis shardedJedis = null ;
- 尝试{
- //从连接池中获取jedis分片对象
- shardedJedis = shardedJedisPool.getResource();
- //设置值到redis中
- 返回 shardedJedis.set(key,value);
- } catch (Exception e){
- 的System.out.println(e.getMessage());
- } finally {
- if (null != shardedJedis){
- shardedJedis.close();
- }
- }
- 返回null ;
- }
- }
首先,我们创建一个接口类,该接口定义Jedis 的操作,代码如下:
- 公共接口 RedisOperations {
- T执行(ConnectionCallback <T>动作);
- String set(final String key, final String value);
- String get(final String key);
- }
最后定义具体的操作服务类,代码如下:
- @Service (“redisTemplate” )
- 公共类 RedisTemplate 实现 RedisOperations {
- @Resource (name = “shardedJedisPool” )
- 私人 ShardedJedisPool shardedJedisPool;
- @覆盖
- public <T> T execute(ConnectionCallback <T> action){
- ShardedJedis shardedJedis = null ;
- 尝试{
- //从连接池中获取jedis分片对象
- shardedJedis = shardedJedisPool.getResource();
- return action.doInRedis(shardedJedis);
- } catch (Exception e){
- 的System.out.println(e.getMessage());
- } finally {
- if (null != shardedJedis){
- shardedJedis.close();
- }
- }
- 返回null ;
- }
- / **
- *注意:真正封装的方法,非常的简洁干脆
- * /
- public String set(final String key, final String value){
- return execute(new ConnectionCallback <String>(){
- @覆盖
- public String doInRedis(
- ShardedJedis shardedJedis){
- 返回 shardedJedis.set(key,value);
- }
- });
- }
- public String get(final String key){
- return execute(new ConnectionCallback <String>(){
- @覆盖
- public String doInRedis(ShardedJedis shardedJedis){
- 返回 shardedJedis.get(key);
- }
- });
- }
- }
如果大家对spring jdbc 或者是spring数据 Redis的源码研究过,就应该知道JdbcTemplate 和RedisTemplate 这两个类,这两个框架中用到了大量的回调机制,下面我们就以spring数据 redis为例,来简单的看下高手是如何玩转回调机制的。
首先定义回调方法,代码如下:
其次,定义操作方法,代码如下:- 公共接口 RedisOperations <K,V> {
- 执行(RedisCallback <T>动作);
- 执行(SessionCallback <T> session);
- ............省略若干方法............
- }
- public class RedisTemplate <K,V> 扩展 RedisAccessor 实现 RedisOperations <K,V> {
- //以下定义的是Redis支持的操作类型,例如SetOperations就是用来操作设置类型的,由于Redis支持的操作类型比较多,所以将每种操作类型都抽象成一个具体的操作类
- 私人 ValueOperations <K,V> valueOps;
- private ListOperations <K,V> listOps;
- 私人 SetOperations <K,V> setOps;
- 私有 ZSetOperations <K,V> zSetOps;
- 私人 HyperLogLogOperations <K,V> hllOps;
- / **
- *构造一个新的<code> RedisTemplate </ code>实例。
- * /
- public RedisTemplate(){}
- public <T> T execute(RedisCallback <T> action){
- return execute(action,isExposeConnection());
- }
- public <T> T execute(RedisCallback <T> action, boolean exposedConnection){
- return execute(action,exposedConnection, false );
- }
- public <T> T execute(RedisCallback <T> action, boolean exposedConnection, boolean pipeline){
- Assert.isTrue(已初始化, “模板未初始化;在使用之前调用afterPropertiesSet()” );
- Assert.notNull(action, “Callback object must not be null” );
- //获取Redis服务器的连接工厂
- RedisConnectionFactory factory = getConnectionFactory();
- RedisConnection conn = null ;
- 尝试 {
- if (enableTransactionSupport){
- //仅在潜在事务同步的情况下才绑定资源
- //如果开启了事物的话,需将连接绑定到事物上
- 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);
- //关闭管道
- if (pipeline &&!pipelineStatus){
- connToUse.closePipeline();
- }
- // TODO:任何其他连接处理?
- return postProcessResult(result,connToUse,existingConnection);
- } finally {
- if (enableTransactionSupport){
- RedisConnectionUtils.unbindConnection(工厂);
- } else {
- RedisConnectionUtils.releaseConnection(conn,factory);
- }
- }
- }
- public <T> T execute(SessionCallback <T> session){
- Assert.isTrue(已初始化, “模板未初始化;在使用之前调用afterPropertiesSet()” );
- Assert.notNull(session, “Callback object must not be null” );
- RedisConnectionFactory factory = getConnectionFactory();
- //绑定连接
- RedisConnectionUtils.bindConnection(factory,enableTransactionSupport);
- 尝试 {
- return session.execute(this );
- } finally {
- RedisConnectionUtils.unbindConnection(工厂);
- }
- }
- ............省略若干创建连接代码............
- ............以下是具体的操作,会调用回调方法............
- protected List <Object> execRaw(){
- return execute(new RedisCallback <List <Object >>(){
- public List <Object> doInRedis(RedisConnection connection) throws DataAccessException {
- return connection.exec();
- }
- });
- }
- public void delete(K key){
- final byte [] rawKey = rawKey(key);
- execute(new RedisCallback <Object>(){
- public Object doInRedis(RedisConnection connection){
- connection.del(rawKey);
- 返回null ;
- }
- }, true );
- }
- public void delete(Collection <K> keys){
- if (CollectionUtils.isEmpty(keys)){
- 返回;
- }
- final byte [] [] rawKeys = rawKeys(keys);
- execute(new RedisCallback <Object>(){
- public Object doInRedis(RedisConnection connection){
- connection.del(rawKeys);
- 返回null ;
- }
- }, true );
- }
- }