如何通过Spring配置多次实例化带不同依赖的服务?
解决方案:Spring中实现多实例领域服务(带不同依赖)
方案一:使用@Qualifier区分同类型Bean
通过给不同环境的Bean添加唯一标识,明确绑定领域服务的依赖,同时让应用层能精准注入对应实例。
修改配置类
OfflineConfig
@Configuration class OfflineConfig { @Bean @Qualifier("offlineEventBus") fun offlineEventBus(): EventBus { return InMemoryEventBus() } @Bean @Qualifier("offlineCommandBus") fun offlineCommandBus(): CommandBus { return InMemoryCommandBus() } @Bean @Qualifier("offlineDoSomethingHandler") fun offlineDoSomethingCommandHandler( @Qualifier("offlineEventBus") eventBus: EventBus, @Qualifier("offlineCommandBus") commandBus: CommandBus, useCase: UseCase<DoSomething>, someRepo: SomeRepository ): CommandHandler<DoSomething> { return CommandHandler(eventBus, commandBus, useCase, DoSomething::class.java, someRepo) } @Bean @Qualifier("offlineDoSomethingElseHandler") fun offlineDoSomethingElseCommandHandler( @Qualifier("offlineEventBus") eventBus: EventBus, @Qualifier("offlineCommandBus") commandBus: CommandBus, useCase: UseCase<DoSomethingElse>, someRepo: SomeRepository ): CommandHandler<DoSomethingElse> { return CommandHandler(eventBus, commandBus, useCase, DoSomethingElse::class.java, someRepo) } }
OnlineConfig
@Configuration class OnlineConfig { @Bean @Qualifier("onlineEventBus") fun onlineEventBus(): EventBus { return OnlineEventBus() } @Bean @Qualifier("onlineCommandBus") fun onlineCommandBus(): CommandBus { return OnlineCommandBus() } @Bean @Qualifier("onlineDoSomethingHandler") fun onlineDoSomethingCommandHandler( @Qualifier("onlineEventBus") eventBus: EventBus, @Qualifier("onlineCommandBus") commandBus: CommandBus, useCase: UseCase<DoSomething>, someRepo: SomeRepository ): CommandHandler<DoSomething> { return CommandHandler(eventBus, commandBus, useCase, DoSomething::class.java, someRepo) } @Bean @Qualifier("onlineDoSomethingElseHandler") fun onlineDoSomethingElseCommandHandler( @Qualifier("onlineEventBus") eventBus: EventBus, @Qualifier("onlineCommandBus") commandBus: CommandBus, useCase: UseCase<DoSomethingElse>, someRepo: SomeRepository ): CommandHandler<DoSomethingElse> { return CommandHandler(eventBus, commandBus, useCase, DoSomethingElse::class.java, someRepo) } }
应用层注入使用
@Component class AppService { @Autowired @Qualifier("offlineDoSomethingHandler") private lateinit var offlineHandler: CommandHandler<DoSomething> @Autowired @Qualifier("onlineDoSomethingHandler") private lateinit var onlineHandler: CommandHandler<DoSomething> // 业务方法中按需使用对应Handler fun handleOfflineTask() { offlineHandler.execute(DoSomething()) } fun handleOnlineTask() { onlineHandler.execute(DoSomething()) } }
方案二:创建独立Spring子上下文隔离配置
如果两套服务需要完全隔离(避免任何Bean冲突),可以创建多个独立的ApplicationContext,分别加载对应配置,还可通过父上下文共享公共Bean(如Repository、UseCase)。
实现代码
// 父上下文加载公共依赖(如Repository、UseCase) val parentContext = AnnotationConfigApplicationContext(CommonConfig::class.java) // 加载Offline环境上下文 val offlineContext = AnnotationConfigApplicationContext().apply { parent = parentContext register(OfflineConfig::class.java, MyDomainConfig::class.java) refresh() } val offlineDoSomethingHandler = offlineContext.getBean(CommandHandler<DoSomething>::class.java) // 加载Online环境上下文 val onlineContext = AnnotationConfigApplicationContext().apply { parent = parentContext register(OnlineConfig::class.java, MyDomainConfig::class.java) refresh() } val onlineDoSomethingHandler = onlineContext.getBean(CommandHandler<DoSomething>::class.java)
方案选择建议
- 方案一:适合大部分场景,配置简单,Bean共享性高,仅通过标识区分不同实例。
- 方案二:适合两套服务依赖完全独立、冲突较多的场景,完全隔离上下文,避免任何Bean命名或依赖冲突,但需手动管理上下文生命周期。
内容的提问来源于stack exchange,提问作者Grégory Elhaimer
相关产品推荐
相关产品推荐

