RedisConfig中禁止构造器注入业务Service、禁止@Autowired自身声明的RedisTemplate、禁止注入GenericObjectPoolConfig;应仅配置基础设施,用方法参数注入依赖,保持无状态。

RedisConfig里用构造器注入了Service会导致循环依赖
Spring Boot启动时检测到循环依赖,如果源头在RedisConfig类,大概率是因为你在配置类里直接通过构造器注入了业务Service(比如UserServiceImpl),而该Service又反过来依赖RedisTemplate或StringRedisTemplate——这就形成了A→B→A闭环。
这种写法看似“解耦”,实则把原本松散的依赖链硬生生拧成了死结。Spring在创建RedisConfig前必须先准备好它要注入的Service,但那个Service又需要RedisTemplate,而RedisTemplate又依赖RedisConfig(比如自定义序列化器、连接工厂等)。
- 不要在
RedisConfig中构造器注入任何业务Service或Repository - 如果真要复用业务逻辑(极少见),改用
@Lazy修饰构造器参数,例如:public RedisConfig(@Lazy UserService userService) - 更合理的做法是把业务逻辑完全移出配置类,让
RedisConfig只负责RedisConnectionFactory、RedisTemplate、GenericObjectPoolConfig等基础设施的声明
RedisConfig里@Autowired字段注入了RedisTemplate本身
你可能在RedisConfig里写了类似这样的代码:
@Configuration
public class RedisConfig {
@Autowired
private RedisTemplate<String, Object> redisTemplate; // ❌ 错误:自己依赖自己
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// ...
}
}
这会导致Spring在准备创建redisTemplate Bean前,先尝试注入已存在的redisTemplate,但此时它还没造出来——典型的“自己等自己”。这个错误在Spring Boot 2.6+会直接失败,因为默认禁用了循环引用。
- 配置类内部不要
@Autowired任何正在被@Bean声明的同类型实例 - 如需在
@Bean方法内复用其他Bean,用方法参数注入,Spring会自动解析:public RedisTemplate redisTemplate(RedisConnectionFactory factory, ObjectMapper objectMapper) - 如果非要用字段注入,确保字段类型和
@Bean返回类型不一致(比如注入StringRedisTemplate,但声明RedisTemplate<String, Object>)
检查GenericObjectPoolConfig是否被意外注入进RedisConfig
有些开发者为了“精细化控制连接池”,会在RedisConfig里手动@Autowired一个GenericObjectPoolConfig,再传给LettuceClientConfigurationBuilder。但这个类本身不是Spring管理的Bean,也不会被自动注册——结果就是NullPointerException或间接触发循环依赖检测(因为Spring试图用代理/工厂兜底)。
-
GenericObjectPoolConfig应该用new创建,而不是注入;它只是个普通POJO - 正确姿势是:在
@Bean方法里构造并配置它,然后交给LettucePoolingClientConfiguration.builder().poolConfig(...) - 如果你看到报错堆栈里有
GenericObjectPoolConfig和RedisConfig反复出现,基本可以断定是这里出了问题
为什么加了spring.main.allow-circular-references=true也不行
开启允许循环引用只能绕过Spring的检测机制,但不能解决根本问题。如果RedisConfig里存在上述任一写法,即使配置了spring.main.allow-circular-references=true,应用仍可能在运行时抛出BeanCurrentlyInCreationException或NullPointerException——因为依赖关系依然不满足初始化条件。
- 这个配置只是“睁一只眼”,不是“治本之药”
- 它对字段/Setter注入的单例Bean有效,但对构造器注入、原型Bean、或配置类内部自引用完全无效
- 真正要做的,是让
RedisConfig保持“无状态”:不持有业务对象,不反向依赖自身声明的Bean,不参与业务流程编排


















