1.问题描述
2.解决思路
3.解决问题
4.使用方法
一个需求,需要一个组件对接redis,需要支持多个DB的切换,以及序列化和反序列的管理,并且不对以往代码造成影响,且可以支持SPI形式的接入.
声明一个Enable注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import({RedisBeanAutoConfig.class})
public @interface EnableRedisDbs {
}
用Import注入Bean
@Slf4j
@Component
public class RedisBeanAutoConfig {
@Autowired
private RedisTemplate redisTemplate;
@Bean
@ConditionalOnMissingBean(RedisSerializerManager.class)
public RedisSerializerManager getRedisSerializerManager(){
return new RedisSerializerManager();
}
@Bean
public RedisDbsTemplate redisDbsEntity(Environment environment, RedisSerializerManager redisSerializerManager, ApplicationContext applicationContext){
LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
return new RedisDbsTemplate(environment, connectionFactory,redisSerializerManager,applicationContext);
}
}
使用2.X原本的Lettuce链接池,并且取出它里面的配置文件
@Slf4j
public class RedisDbsTemplate {
private final static Map<Integer, RedisTemplate> redisTemplateMap = new HashMap<Integer, RedisTemplate>();
private Environment environment;
private LettuceConnectionFactory connectionFactory;
private RedisSerializerManager redisSerializerManager;
private DefaultListableBeanFactory beanFactory;
public RedisDbsTemplate(Environment environment, LettuceConnectionFactory connectionFactory, RedisSerializerManager redisSerializerManager, ApplicationContext applicationContext){
this.environment=environment;
this.connectionFactory=connectionFactory;
this.redisSerializerManager=redisSerializerManager;
this.beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
init();
}
private void init() {
String property = environment.getProperty("spring.redis.databases");
String beanPrefix = environment.getProperty("spring.redis.beanPrefix","redis_db_");
if (StringUtils.isEmpty(property)) {
log.warn("'spring.redis.databases' No settings");
return;
}
String[] dbs = property.split(",");
for (String db : dbs) {
int dbIndex = NumberUtils.toInt(db);
RedisTemplateBuilder redisTemplateBuilder = new RedisTemplateBuilder(dbIndex, connectionFactory,redisSerializerManager);
RedisTemplate redisTemplate = redisTemplateBuilder.builder();
redisTemplateMap.put(dbIndex,redisTemplate);
//动态注入到Spring的BeanFactory
this.beanFactory.registerSingleton(beanPrefix+db,redisTemplate);
}
}
public RedisTemplate getRedisTemplate(int i){
return redisTemplateMap.get(i);
}
}
生成一个RedisDbsTemplate Bean,并且把小的RedisTemplate指定名称注入到BeanFactory中
public class RedisTemplateBuilder {
private int dbIndex;
private LettuceConnectionFactory connectionFactory;
private RedisSerializerManager.RedisSerializerEntity redisSerializerEntity= RedisSerializerManager.getDefKeyValueSerializer();
public RedisTemplateBuilder(int dbIndex, LettuceConnectionFactory connectionFactory, RedisSerializerManager redisSerializerManager) {
this.dbIndex = dbIndex;
this.connectionFactory = connectionFactory;
RedisSerializerManager.RedisSerializerEntity redisSerializerEntity = redisSerializerManager.get(dbIndex);
if (redisSerializerEntity !=null) {
this.redisSerializerEntity= redisSerializerEntity;
}
}
public RedisTemplate builder() {
RedisTemplate<Serializable, Object> redisTemplate = new RedisTemplate<Serializable, Object>();
RedisConnectionFactory factory = this.getFactory(dbIndex);
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(redisSerializerEntity.getKeySerializer());
redisTemplate.setValueSerializer(redisSerializerEntity.getValueSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
private RedisConnectionFactory getFactory(int i) {
RedisStandaloneConfiguration standaloneConfiguration = connectionFactory.getStandaloneConfiguration();
standaloneConfiguration.setDatabase(i);
LettuceClientConfiguration clientConfiguration = connectionFactory.getClientConfiguration();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(standaloneConfiguration, clientConfiguration);
lettuceConnectionFactory.afterPropertiesSet();
return lettuceConnectionFactory;
}
}
声明一个序列化管理的类
public class RedisSerializerManager {
/**
* 默认的序列化方案
*/
private static RedisSerializer defRedisSerializer;
/**
* 默认的序列化方案
*/
private static RedisSerializerEntity defKeyValueSerializer;
static {
defRedisSerializer = new StringRedisSerializer();
defKeyValueSerializer = new RedisSerializerEntity();
defKeyValueSerializer.setKeySerializer(defRedisSerializer);
defKeyValueSerializer.setValueSerializer(defRedisSerializer);
}
private Map<Integer, RedisSerializerEntity> serializerMap = new HashMap<>();
public static RedisSerializerEntity getDefKeyValueSerializer() {
return defKeyValueSerializer;
}
public static void setDefKeyValueSerializer(RedisSerializerEntity defKeyValueSerializer) {
RedisSerializerManager.defKeyValueSerializer = defKeyValueSerializer;
}
/**
* @param dbIndex dbIndex
* @param redisSerializerEntity
*/
public void put(Integer dbIndex, RedisSerializerEntity redisSerializerEntity) {
serializerMap.put(dbIndex, redisSerializerEntity);
}
public RedisSerializerEntity get(Integer dbIndex) {
return serializerMap.get(dbIndex);
}
public static RedisSerializer getDefRedisSerializer() {
return defRedisSerializer;
}
public static void setDefRedisSerializer(RedisSerializer defRedisSerializer) {
RedisSerializerManager.defRedisSerializer = defRedisSerializer;
}
/**
* key和value的序列化方案组
*/
public static class RedisSerializerEntity {
/**
* key的序列化方案
*/
private RedisSerializer<?> keySerializer = defRedisSerializer;
/**
* value的序列化方案
*/
private RedisSerializer<?> valueSerializer = defRedisSerializer;
public RedisSerializer<?> getKeySerializer() {
return keySerializer;
}
public void setKeySerializer(RedisSerializer<?> keySerializer) {
this.keySerializer = keySerializer;
}
public RedisSerializer<?> getValueSerializer() {
return valueSerializer;
}
public void setValueSerializer(RedisSerializer<?> valueSerializer) {
this.valueSerializer = valueSerializer;
}
}
}
1.注解@EnableRedisDbs(可以修改为META-INF方案)
2.配置spring.redis.databases
内容为db的index使用','间隔
3.配置spring.redis.beanPrefix
用于按名称注入redistemplate的前缀,默认'redis_db_'
4.注入RedisDbsTemplate,使用时getRedisTemplate(dbIndex);
5.使用
@Autowired
@Qualifier("redis_db_X")
private RedisTemplate redisTemplate;
X为dbIndex;
6.使用RedisSerializerManager为每一个DB_redisTemplate定制序列化方案