【发布时间】:2019-09-13 01:12:47
【问题描述】:
在我们的基础架构中,我们将 Redis 与 Dynomite 结合使用,以在数据中心上进行复制并实现高可用性。 我们的一个应用程序是 Java 的,我们主要使用 Spring 生态系统。
在这个应用程序中,我们使用 spring-session 管理会话,并使用 Redis 集群来存储会话。
Spring 会话正在使用 Dynomite 上下文中不允许的 pub/sub 命令,因此我们需要自定义存储库。
我尝试这样做,但我遇到了 spring-boot 和自动配置类的问题。
请在下面找到我们的部分代码。
build.gradle 中的依赖项
val springBootVersion = "2.1.4.RELEASE"
val springSessionDataRedisVersion = "2.1.5.RELEASE"
implementation("org.springframework.boot:spring-boot-starter-security:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-data-redis:$springBootVersion")
implementation("org.springframework.session:spring-session-data-redis:$springSessionDataRedisVersion")
我们的配置类用我们的自定义类覆盖 sessionRepository
@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
@Bean
public SessionRepository sessionRepository() {
return new RedisDynoSessionRepository();
}
}
sessionRepository 自定义类
public class RedisDynoSessionRepository implements SessionRepository {
...
}
当我们运行我们的应用程序时,我们在 bean 中发生了冲突,因为应用程序发现 bean 会话存储库是已知的。
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'sessionRepository' defined in class path resource [com/orange/ccmd/spring/redis/SessionConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=sessionConfig; factoryMethodName=sessionRepository; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/orange/ccmd/spring/redis/SessionConfig.class]] for bean 'sessionRepository': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration; factoryMethodName=sessionRepository; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]] bound.
我正在寻找绕过此问题的方法,可能是取消注册 bean?
感谢您的帮助。
[编辑]
我在 bean 上尝试了 @Primary,但它不起作用。
如果我以不同的方式命名我的 bean,Spring 将使用标准 bean 而不是我自定义的新 bean。
如果我以相同的方式命名它,则会出现冲突错误。
如果我把覆盖 bean 配置 (spring.main.allow-bean-definition-overriding=true),我有一个错误,因为 2 个 bean 没有相同的类型。这是我打算做的,因为我不想在我的仓库中传递消息。
【问题讨论】:
-
@DarrenForsythe 不,我认为这无关。就我而言,我尝试注册我的 bean 而不是标准的 redis 存储库 bean。我不想允许覆盖 bean,因为我认为这可能很危险。
-
你试过重命名 bean 吗?由于名称冲突而不是类型,会发生覆盖异常。
-
我想我不能更改 bean 的名称,因为 Spring-Data-Redis 使用这个 bean 作为存储库,我想提供我自己的存储库版本。所以我认为它必须具有相同的名称。
-
当然,但我不认为它取决于名称自动装配?例如如果您将方法名称更改为
redisDynoSessionRepository是否有效?如果您必须将它们命名为相同的名称,那么您别无选择,只能启用 bean 覆盖。
标签: java spring spring-boot spring-data-redis spring-session