Spring Boot多Redis配置启动报错,需同时使用两个RedisTemplate
Spring Boot多Redis实例配置冲突解决(无需设置Primary)
问题场景
需配置两个独立Redis实例,分别用于Token和Invoice数据存储,已编写InvoiceRedisConfiguration和TokenRedisConfiguration配置类,但启动应用时触发Bean冲突报错。
报错信息
Parameter 0 of method reactiveRedisTemplate in org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration required a single bean, but 2 were found: - invoiceRedisFactory: defined by method 'invoiceRedisFactory' in class path resource [tsp/third/party/api/tsp/api/database/connections/invoice/InvoiceRedisConfiguration.class] - tokenRedisFactory: defined by method 'tokenRedisFactory' in class path resource [tsp/third/party/api/tsp/api/database/connections/token/TokenRedisConfiguration.class]
原因分析
Spring Boot自动配置类RedisReactiveAutoConfiguration会尝试创建默认ReactiveRedisTemplate,该Bean依赖单个LettuceConnectionFactory实例。由于自定义了两个LettuceConnectionFactoryBean,Spring无法自动选择,导致冲突。
解决方案
1. 排除Redis自动配置类
在Spring Boot启动类中排除RedisReactiveAutoConfiguration,避免自动创建冲突的Reactive模板:
@SpringBootApplication(exclude = RedisReactiveAutoConfiguration.class) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
2. 保留自定义配置类(无需修改)
你的配置类已通过@Qualifier明确标记Bean,可直接使用:
InvoiceRedisConfiguration
@Configuration public class InvoiceRedisConfiguration { @Value("${spring.redis.invoice.host:localhost}") private String redisHost; @Value("${spring.redis.invoice.port:6379}") private int redisPort; @Bean @Qualifier("invoiceRedisFactory") public LettuceConnectionFactory invoiceRedisFactory(){ return new LettuceConnectionFactory( new RedisStandaloneConfiguration(redisHost,redisPort) ); } @Bean @Qualifier("invoiceRedisTemplate") public RedisTemplate<String, Invoice> invoiceRedisTemplate(@Qualifier("invoiceRedisFactory") LettuceConnectionFactory invoiceRedisFactory){ RedisTemplate<String, Invoice> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(invoiceRedisFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
TokenRedisConfiguration
@Configuration public class TokenRedisConfiguration { @Value("${spring.redis.host:localhost}") private String redisHost; @Value("${spring.redis.port:6379}") private int redisPort; @Bean @Qualifier("tokenRedisFactory") public LettuceConnectionFactory tokenRedisFactory(){ return new LettuceConnectionFactory( new RedisStandaloneConfiguration(redisHost,redisPort) ); } @Bean @Qualifier("tokenRedisTemplate") public RedisTemplate<String,Token> tokenRedisTemplate(@Qualifier("tokenRedisFactory") LettuceConnectionFactory tokenRedisFactory){ RedisTemplate<String, Token> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(tokenRedisFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Token.class)); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Token.class)); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
3. 注入时指定Bean标识
在业务类中通过@Qualifier明确指定要注入的RedisTemplate:
Token业务类示例
@Service public class TokenService { private final RedisTemplate<String, Token> tokenRedisTemplate; public TokenService(@Qualifier("tokenRedisTemplate") RedisTemplate<String, Token> tokenRedisTemplate) { this.tokenRedisTemplate = tokenRedisTemplate; } public void saveToken(String key, Token token) { tokenRedisTemplate.opsForValue().set(key, token); } }
Invoice业务类示例
@Service public class InvoiceService { private final RedisTemplate<String, Invoice> invoiceRedisTemplate; public InvoiceService(@Qualifier("invoiceRedisTemplate") RedisTemplate<String, Invoice> invoiceRedisTemplate) { this.invoiceRedisTemplate = invoiceRedisTemplate; } public void saveInvoice(String key, Invoice invoice) { invoiceRedisTemplate.opsForValue().set(key, invoice); } }
说明
排除RedisReactiveAutoConfiguration后,Spring不再自动创建默认Reactive Redis模板,完全使用自定义的两个Redis实例配置,既满足多实例需求,又避免Bean冲突。
内容的提问来源于stack exchange,提问作者Masoud Niki
相关产品推荐
相关产品推荐

