You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SpringBootTest中指定nameGenerator解决Bean名称冲突

问题:@SpringBootTest指定部分类测试时Bean名称冲突,如何配置Bean名称生成器?

当用@SpringBootTest指定特定类执行测试时,由于存在两个不同包但同名的ConflictName Bean,会抛出BeanDefinitionOverrideException异常:

测试代码:

@SpringBootTest(
    classes = [BarService::class, ConflictName::class, com.foo.ConflictName::class, FooService::class]
)
class DemoApplicationTests

异常信息:

Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: 
Invalid bean definition with name 'conflictName' defined in null:
Cannot register bean definition [Generic bean: class [com.foo.ConflictName]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null] 
for bean 'conflictName' since there is already [Generic bean: class [com.bar.ConflictName]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null] bound.

但如果不指定具体类,直接运行全应用测试则能成功执行:

@SpringBootTest
class DemoApplicationTests

已知在@SpringBootApplication中可以通过nameGenerator = FullyQualifiedAnnotationBeanNameGenerator::class配置全类名作为Bean名称来避免冲突,想知道怎么在@SpringBootTest里实现同样的配置?

完整代码示例

package com.bar

import org.springframework.stereotype.Service

@Service
class BarService(private val conflictName: ConflictName)
package com.bar

import org.springframework.stereotype.Component

@Component
class ConflictName
package com.foo

import org.springframework.stereotype.Component

@Component
class ConflictName
package com.foo

import org.springframework.stereotype.Service

@Service
class FooService(private val conflictName: ConflictName)
package com

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator

@SpringBootApplication(nameGenerator = FullyQualifiedAnnotationBeanNameGenerator::class)
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

解决方案

@SpringBootTest本身没有直接提供nameGenerator属性,但可以通过两种方式实现需求:

方式一:自定义测试配置类,指定Bean名称生成器

创建测试专用的配置类,通过@ComponentScan指定要扫描的类(或包),同时配置全类名作为Bean名称生成器:

import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator
import org.springframework.context.annotation.ComponentScan

@Configuration
@ComponentScan(
    basePackageClasses = [BarService::class, FooService::class],
    nameGenerator = FullyQualifiedAnnotationBeanNameGenerator::class
)
class TestConfig

然后修改测试类,引入该配置:

@SpringBootTest(classes = [TestConfig::class])
class DemoApplicationTests

方式二:用@ContextConfiguration指定自定义容器初始化器

如果需要明确指定测试类,可自定义ApplicationContextInitializer来设置Bean名称生成器:

import org.springframework.context.ApplicationContextInitializer
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator

class BeanNameGeneratorInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
    override fun initialize(context: ConfigurableApplicationContext) {
        val beanFactory = context.beanFactory as org.springframework.beans.factory.support.DefaultListableBeanFactory
        beanFactory.beanNameGenerator = FullyQualifiedAnnotationBeanNameGenerator()
    }
}

然后在测试类中配置初始化器:

@SpringBootTest(
    classes = [BarService::class, ConflictName::class, com.foo.ConflictName::class, FooService::class]
)
@ContextConfiguration(initializers = [BeanNameGeneratorInitializer::class])
class DemoApplicationTests

内容的提问来源于stack exchange,提问作者Anton Balaniuc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:35:13