Spring中@Primary注解失效:RedisIndexedSessionRepository Bean覆盖异常
为什么@Primary注解没生效?
这个问题的核心原因在于Spring处理@Configuration内部类依赖的逻辑,以及你覆盖Bean的方式不对。
让我拆解一下关键问题点:
- 你继承了
RedisHttpSessionConfiguration后,定义了一个新的customSessionRepository()方法并标注@Primary,但父类本身的sessionRepository()方法仍然会被Spring注册为独立Bean——这直接导致容器里存在两个RedisIndexedSessionRepository类型的Bean。 SessionCleanupConfiguration是RedisHttpSessionConfiguration的内部@Configuration类,它的构造器依赖RedisIndexedSessionRepository。Spring处理这类内部配置类的依赖时,会优先绑定到当前外层配置类(也就是父类RedisHttpSessionConfiguration)中定义的sessionRepository()方法返回的实例,不会去全局查找@Primary标注的Bean。这就导致即使你加了@Primary,内部的SessionCleanupConfiguration还是会尝试使用父类的Bean,最终因为容器里有两个同类型Bean而抛出冲突错误。
解决方案:重写父类的@Bean方法,而非定义新方法
正确的做法是直接重写父类的sessionRepository()方法,而不是创建新的方法名。这样Spring只会注册你重写后的Bean,不会产生同类型Bean冲突,甚至连@Primary都不需要(当然加上也没问题):
@EnableRedisHttpSession @Configuration public class CustomRedisHttpSessionConfiguration extends RedisHttpSessionConfiguration { @Override @Bean public RedisIndexedSessionRepository sessionRepository() { // 调用父类方法获取基础实例 RedisIndexedSessionRepository repository = super.sessionRepository(); // 在这里添加你的自定义配置逻辑 // 示例:repository.setDefaultMaxInactiveInterval(1800); return repository; } }
这么做的优势:
- 完全覆盖父类的
sessionRepositoryBean,容器里只会存在你自定义的这一个实例。 SessionCleanupConfiguration的构造器依赖会自动绑定到你重写后的Bean,因为Spring会优先使用当前配置类(你的子类)中的sessionRepository()方法返回值。
补充:为什么原方式的@Primary不生效?
再细化一下底层逻辑:Spring处理@Configuration类时,会为配置类生成代理对象。对于内部@Configuration类(比如SessionCleanupConfiguration),它的依赖注入会优先依赖外层配置类的@Bean方法调用,而非从BeanFactory中查找全局Bean。所以即使你在子类中定义了@Primary的Bean,父类内部的SessionCleanupConfiguration仍然会绑定到父类的sessionRepository()方法,最终引发冲突。
内容的提问来源于stack exchange,提问作者jarst
相关产品推荐
相关产品推荐

