这里的实现,是通过调用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方法
/** * 实例化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)添加在对应的方法体上即可。