这里的实现,是通过调用Redis的工具类,通过Spring的AOP来实现切换库。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisSelect {
/**
* redis库 0 - 15 库
* @return
*/
int value() default 0;
}
/**
* 环绕增强标注 RedisSelect 注解的方法
* @author Mrlv
* @date 2021/12/19 16:15
* @param point
* @return java.lang.Object
*/
@Around("@annotation(com.mrlv.redis.annotation.RedisSelect)")
@ConditionalOnBean(SelectableRedistemplate.class)
public Object configRedis(ProceedingJoinPoint point) throws Throwable{
int db = defaultDataBase;
try {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getmethod();
RedisSelect config = method.getAnnotation(RedisSelect.class);
if(config != null){
db = config.value();
}
RedisSelectSupport.select(db);
return point.proceed();
} finally {
//在环绕通知执行回调完成后 重置 RedisSelectSupport 中的静态 db
RedisSelectSupport.select(defaultDataBase);
//logger.debug("redis 重置db {} 到 {}", db, defaultDataBase);
}
}
然后我们创建一个类,定义一个静态变量 (TransmittableThreadLocal可以自己去了解,简单来说解决线程池传递值的问题)。
/**
* Redis 切换DB配置
*/
public class RedisSelectSupport {
private static final TransmittableThreadLocal<Integer> SELECT_CONTEXT = new TransmittableThreadLocal<>();
public static void select(int db) {
SELECT_CONTEXT.set(db);
}
public static Integer getSelect() {
return SELECT_CONTEXT.get();
}
}
接下来自定义SelectableRedistemplate类继承并重写Redistemplate的preProcessConnection方法。
public class SelectableRedistemplate<K, V> extends Redistemplate<K, V> {
@Override
protected RedisConnection createRedisConnectionProxy(RedisConnection pm) {
return super.createRedisConnectionProxy(pm);
}
/**
* 在连接Redis之前做一些配置
* @param connection
* @param existingConnection
* @return
*/
@Override
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
Integer db = RedisSelectSupport.getSelect();
if(db != null){
//切换 redis db 到 其他的库
connection.select(db);
}
return super.preProcessConnection(connection, existingConnection);
}
}
/**
* 实例化Redistemplate对象
* @return
*/
@Bean
@ConditionalOnMissingBean
public SelectableRedistemplate<String, Object> functionDomainRedistemplate(RedisConnectionFactory redisConnectionFactory, RedisSerializer redisMyStringSerializer) {
SelectableRedistemplate<String, Object> redistemplate = new SelectableRedistemplate<String, Object>();
redistemplate.setConnectionFactory(redisConnectionFactory);
redistemplate.afterPropertiesSet();
log.info("实例化 Redistemplate 对象完成");
return redistemplate;
}
即可。
使用方法
@RedisSelect(4)添加在对应的方法体上即可。