1.原始redis操作实现
public void test(){
// 1.封装config
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(20);
poolConfig.setMaxTotal(200);
poolConfig.setMaxWaitMillis(2000);
// 2.创建jedis池
Pool pools = new JedisPool(poolConfig,"localhost",6379,2000,null,false);
// 3.获取jedis
Jedis jedis = pools.getResource();
// 4.jedis操作
jedis.set("name".getBytes(), "lucy".getBytes());
boolean exists = jedis.exists("name");
System.out.println(exists);
}
主要步骤分四步,主要是创建jedis连接池,然后从连接池中获取jedis连接,最后使用jedis来进行实际操作
RedisTemplate也基本是按照这个步骤来实现的,只是将共有方法抽象出来
2.RedisTemplate的实现
1)创建RedisConfig类,用于创建JedisPoolConfig、RedisConnectionFactory、RedisTemplate
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory){
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
@Bean
public RedisConnectionFactory connectionFactory(JedisPoolConfig poolConfig){
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);
jedisConnectionFactory.setHostName("localhost");
jedisConnectionFactory.setPort(6379);
return jedisConnectionFactory;
}
@Bean
public JedisPoolConfig poolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(20);
jedisPoolConfig.setMaxTotal(200);
jedisPoolConfig.setMaxWaitMillis(2000);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestOnCreate(true);
return jedisPoolConfig;
}
}
真正进行操作的是JedisConnection,该Connection是从RedisConnectionFactory中获取的,故需要先创建该Factory
2)创建RedisTest类,进行jedis操作
public class RedisTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(RedisConfig.class);
RedisTemplate redisTemplate = context.getBean(RedisTemplate.class);
redisTemplate.opsForValue().set("name", "jack");
Boolean hasKey = redisTemplate.hasKey("name");
System.out.println(hasKey);
}
}
3.RedisTemplate源码分析
笔者使用的版本为,spring-data-redis-1.8.3.RELEASE.jar
RedisTemplate.hasKey()方法,主要内容如下:
public Boolean hasKey(K key) {
// 1.将对象类型的key转换为byte[]类型
final byte[] rawKey = rawKey(key);
// 2.执行execute方法,主要是为了获取RedisConnection,真正执行在回调方法里
return execute(new RedisCallback() {
public Boolean doInRedis(RedisConnection connection) {
// 3.真正执行方法
return connection.exists(rawKey);
}
}, true);
}
execute()方法内容如下:
public T execute(RedisCallback action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(action, "Callback object must not be null");
// 1.获取连接池工厂,即RedisConfig类中的RedisConnectionFactory bean
RedisConnectionFactory factory = getConnectionFactory();
RedisConnection conn = null;
try {
if (enableTransactionSupport) {
// only bind resources in case of potential transaction synchronization
conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
} else {
// 2.获取连接
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));
// 3.封装连接后,将连接传入回调函数,然后执行真正的操作
T result = action.doInRedis(connToExpose);
// close pipeline
if (pipeline && !pipelineStatus) {
connToUse.closePipeline();
}
// TODO: any other connection processing?
return postProcessResult(result, connToUse, existingConnection);
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
}
}
下面对execute()方法逐步解析
1)获取连接池工厂
public class RedisAccessor implements InitializingBean {
...
private RedisConnectionFactory connectionFactory;
public RedisConnectionFactory getConnectionFactory() {
return connectionFactory;
}
获取工厂这一步,直接从RedisAccessor类中获取,RedisTemplate类继承了RedisAccessor,而在RedisConfig类中可以看到,该RedisConnectionFactory既是我们手动创建的bean
2)获取连接
该步骤可定位到RedisConnectionUtils中,代码如下
public static RedisConnection doGetConnection(RedisConnectionFactory factory, boolean allowCreate, boolean bind,
boolean enableTransactionSupport) {
...
// 主要就是这步操作
RedisConnection conn = factory.getConnection();
...
return conn;
}
具体实现在JedisConnectionFactory.getConnection()中,代码如下
public RedisConnection getConnection() {
if (cluster != null) {
return getClusterConnection();
}
Jedis jedis = fetchJedisConnector();
// 主要步骤
JedisConnection connection = (usePool ? new JedisConnection(jedis, pool, dbIndex, clientName)
: new JedisConnection(jedis, null, dbIndex, clientName));
connection.setConvertPipelineAndTxResults(convertPipelineAndTxResults);
return postProcessConnection(connection);
}
看JedisConnection的源码可知,其封装了Jedis、Pool等域
3)执行回调函数
public Boolean hasKey(K key) {
// 1.将对象类型的key转换为byte[]类型
final byte[] rawKey = rawKey(key);
// 2.执行execute方法,主要是为了获取RedisConnection,真正执行在回调方法里
return execute(new RedisCallback() {
public Boolean doInRedis(RedisConnection connection) {
// 3.真正执行方法
return connection.exists(rawKey);
}
}, true);
}
可以看到真正执行的为connection.exists方法,具体实现类为JedisConnection,方法内容如下:
public Boolean exists(byte[] key) {
try {
if (isPipelined()) {
pipeline(new JedisResult(pipeline.exists(key)));
return null;
}
if (isQueueing()) {
transaction(new JedisResult(transaction.exists(key)));
return null;
}
// 真正执行方法
return jedis.exists(key);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
总结以上步骤可看到,框架封装了获取Connection的过程,用户只需要获取Connection后,直接调用Connection相关方法来操作即可
作者:恐龙弟旺仔
来源:CSDN
原文:https://blog.csdn.net/qq_26323323/article/details/80814576
版权声明:本文为博主原创文章,转载请附上博文链接!