目录
思路:
- Redis数据源信息的配置
通过配置文件配置的方式在配置文件中加入新的Redis数据源信息- ConnectionFactory和RedisTemplate配置
通过BeanFactoryAware向IOC容器中注册,以达到只需要在配置文件配置连接信息就可以动态创建对应的Redis连接的目的
一、 Redis数据源配置
- 创建Redis配置类
@Configuration @ConfigurationProperties(prefix = RedisDataSourceProperties.PREFIX) public class RedisDataSourceProperties { public static final String PREFIX = "spring.redis"; private Map<String, RedisMessageProperties> dataSource; public Map<String, RedisMessageProperties> getDataSource() { return dataSource; } public void setDataSource(Map<String, RedisMessageProperties> dataSource) { this.dataSource = dataSource; } }
- 创建和RedisProperties一样的RedisMessageProperties类
- 此时在配置文件中配置Redis多数据源的配置示例如下
spring: #默认的redis配置 redis: port: 6379 host: 127.0.0.1 password: 123456 database: 2 timeout: 20000ms lettuce: pool: # 最大活跃链接数 默认8 max-active: 3 # 最大空闲连接数 默认8 max-idle: 3 # 最小空闲连接数 默认0 min-idle: 0 client-type: lettuce # 多数据源配置 data-source: # redis1将作为 StringRedisTemplate、RedisCacheUtils和RedisBaseService的名称前缀 redis1: port: 6379 host: 127.0.0.1 password: 123456 database: 3 timeout: 20000ms lettuce: pool: # 最大活跃链接数 默认8 max-active: 3 # 最大空闲连接数 默认8 max-idle: 3 # 最小空闲连接数 默认0 min-idle: 0 # redis2将作为 StringRedisTemplate、RedisCacheUtils和RedisBaseService的名称前缀 redis2: port: 6379 host: 127.0.0.1 password: 123456 database: 4 timeout: 20000ms lettuce: pool: # 最大活跃链接数 默认8 max-active: 3 # 最大空闲连接数 默认8 max-idle: 3 # 最小空闲连接数 默认0 min-idle: 0
二、创建RedisConnection和Template
- 向IOC容器中注册Bean(实现InstantiationAwareBeanPostProcessor接口很关键)
RedisCacheUtils和RedisBaseService是自定义的Redis工具类@Component public class RedisRegister implements BeanFactoryAware, InstantiationAwareBeanPostProcessor { @Autowired private RedisDataSourceProperties redisDataSourceProperties; /** * StringRedisTemplate的beanName后缀 */ public static final String TEMPLATE_NAME = "StringRedisTemplate"; /** * RedisCacheUtils的beanName后缀 */ public static final String UTIL_NAME = "RedisCacheUtils"; /** * RedisBaseService的beanName后缀 */ public static final String SERVICE_NAME = "RedisBaseService"; /** * 读取redis配置并创建对应的StringRedisTemplate * * @param beanFactory * @throws BeansException */ @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory) beanFactory; Map<String, RedisMessageProperties> redisDataSource = redisDataSourceProperties.getDataSource(); if (CollectionUtils.nonEmpty(redisDataSource)) { redisDataSource.forEach((name, dataSource) -> { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); RedisConnectionFactory redisConnection = getRedisConnection(dataSource); stringRedisTemplate.setConnectionFactory(redisConnection); stringRedisTemplate.afterPropertiesSet(); // 向ioc容器中注入StringRedisTemplate String templateName = name + TEMPLATE_NAME; listableBeanFactory.registerSingleton(templateName, stringRedisTemplate); // 向ioc容器中注入RedisCacheUtils RedisCacheUtils redisCacheUtils = new RedisCacheUtils(stringRedisTemplate); String utilName = name + UTIL_NAME; listableBeanFactory.registerSingleton(utilName, redisCacheUtils); // 向ioc容器中注入RedisBaseService RedisBaseService redisBaseService = new RedisBaseService(redisCacheUtils); String serviceName = name + SERVICE_NAME; listableBeanFactory.registerSingleton(serviceName, redisBaseService); }); } } /** * 配置redisConnection * * @param dataSource */ private RedisConnectionFactory getRedisConnection(RedisMessageProperties dataSource) { return getLettuceConnectionFactory(dataSource); } /** * 获取LettuceConnection * * @param dataSource */ private RedisConnectionFactory getLettuceConnectionFactory(RedisMessageProperties dataSource) { RedisStandaloneConfiguration redisConfig = getRedisConfig(dataSource); RedisMessageProperties.Pool pool = dataSource.getLettuce().getPool(); GenericObjectPoolConfig poolConfig = getPoolConfig(pool); LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig).build(); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisConfig, clientConfiguration); connectionFactory.afterPropertiesSet(); return connectionFactory; } /** * 获取连接池配置 * * @param pool */ private GenericObjectPoolConfig getPoolConfig(RedisMessageProperties.Pool pool) { GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(pool.getMaxActive()); poolConfig.setMaxIdle(pool.getMaxIdle()); poolConfig.setMinIdle(pool.getMinIdle()); if (pool.getTimeBetweenEvictionRuns() != null) { poolConfig.setTimeBetweenEvictionRunsMillis(pool.getTimeBetweenEvictionRuns().toMillis()); } if (pool.getMaxWait() != null) { poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis()); } return poolConfig; } /** * 获取redis连接配置 * * @param dataSource */ private RedisStandaloneConfiguration getRedisConfig(RedisMessageProperties dataSource) { RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(); redisConfig.setHostName(dataSource.getHost()); redisConfig.setPort(dataSource.getPort()); redisConfig.setUsername(dataSource.getUsername()); redisConfig.setPassword(RedisPassword.of(dataSource.getPassword())); redisConfig.setDatabase(dataSource.getDatabase()); return redisConfig; } }
- 在项目中使用多个Redis数据源
@Service public class RedisService { /** * 默认配置的 StringRedisTemplate */ @Autowired private StringRedisTemplate stringRedisTemplate; /** * 使用redis1配置的 StringRedisTemplate */ @Autowired @Qualifier("redis1StringRedisTemplate") private StringRedisTemplate redis1StringRedisTemplate; /** * 使用redis2配置的 StringRedisTemplate */ @Autowired @Qualifier("redis2StringRedisTemplate") private StringRedisTemplate redis2StringRedisTemplate; /** * 默认配置的 RedisCacheUtils */ @Autowired private RedisCacheUtils redisCacheUtils; /** * 使用redis1配置的 StringRedisTemplate */ @Autowired @Qualifier("redis1RedisCacheUtils") private RedisCacheUtils redis1RedisCacheUtils; /** * 使用redis2配置的 StringRedisTemplate */ @Autowired @Qualifier("redis2RedisCacheUtils") private RedisCacheUtils redis2RedisCacheUtils; /** * 默认配置的 RedisBaseService */ @Autowired private RedisBaseService redisBaseService; /** * 使用redis1配置的 RedisBaseService */ @Autowired @Qualifier("redis1RedisBaseService") private RedisBaseService redis1RedisBaseService; /** * 使用redis2配置的 RedisBaseService */ @Autowired @Qualifier("redis2RedisBaseService") private RedisBaseService redis2RedisBaseService; }
在 RedisRegister 中需要实现 InstantiationAwareBeanPostProcessor,在IOC容器加载所有bean之前会扫描所有实现了 InstantiationAwareBeanPostProcessor 接口的类
因为RedisRegister需要保证 setBeanFactory(BeanFactory beanFactory) 优先加载,不然在 RedisService中引用的自定义bean会抛NPE
版权声明:本文为qq_41548206原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。