如何在Spring容器中保留同名Bean 解决ConflictingBeanDefinitionException异常
Spring同名第三方Bean冲突解决方案
以下方案均可实现不修改第三方库源码,同时在容器中保留两个同类型不同来源的Bean:
方案1:排除冲突Bean自动注册,手动自定义命名注册
适用于冲突Bean数量较少的场景,操作简单可控。
- 先在全局扫描规则中排除两个库中的冲突类,避免自动注册同名Bean
- 手动通过
@Bean注解注册两个实例,分别指定自定义Bean名称
@Configuration @ComponentScan(basePackages = {"你自己项目的根包", "A库根包", "B库根包"}, excludeFilters = { // 排除两个库中冲突的FetcherAndResolver类的自动注册 @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = com.librarya.component.FetcherAndResolver.class), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = com.libraryb.component.FetcherAndResolver.class) }) public class CustomBeanConfig { // 注册A库的FetcherAndResolver,指定bean名称为fetchFromLibraryA @Bean("fetchFromLibraryA") public FetcherAndResolver fetcherFromA(/* 该类依赖的其他Bean直接写在参数里,Spring会自动注入 */) { return new com.librarya.component.FetcherAndResolver(); } // 注册B库的FetcherAndResolver,指定bean名称为fetchFromLibraryB @Bean("fetchFromLibraryB") public FetcherAndResolver fetcherFromB(/* 该类依赖的其他Bean直接写在参数里,Spring会自动注入 */) { return new com.libraryb.component.FetcherAndResolver(); } }
- 业务代码注入时配合
@Qualifier指定对应Bean名称即可
@Component class ApplicationLogic { @Autowired @Qualifier("fetchFromLibraryA") FetcherAndResolver fetchFromLibraryA; @Autowired @Qualifier("fetchFromLibraryB") FetcherAndResolver fetchFromLibraryB; }
方案2:自定义Bean命名策略,按全类名避免冲突
适用于冲突Bean数量多,逐个排除手动注册成本高的场景。
- 自定义Bean名称生成器,让Spring扫描时用类的全限定名作为Bean名称,不同包下的同名类天然不会冲突
public class FullQualifierNameBeanGenerator extends AnnotationBeanNameGenerator { @Override protected String buildDefaultBeanName(BeanDefinition definition) { return definition.getBeanClassName(); } }
- 在启动类/全局配置类的扫描规则中指定该生成器
@SpringBootApplication @ComponentScan(nameGenerator = FullQualifierNameBeanGenerator.class) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
- 注入时指定对应类的全限定名作为
@Qualifier值即可
@Component class ApplicationLogic { @Autowired @Qualifier("com.librarya.component.FetcherAndResolver") FetcherAndResolver fetchFromLibraryA; @Autowired @Qualifier("com.libraryb.component.FetcherAndResolver") FetcherAndResolver fetchFromLibraryB; }
也可以直接用@Resource注解简化写法:
@Component class ApplicationLogic { @Resource(name = "com.librarya.component.FetcherAndResolver") FetcherAndResolver fetchFromLibraryA; @Resource(name = "com.libraryb.component.FetcherAndResolver") FetcherAndResolver fetchFromLibraryB; }
注意:该方案会修改全局Bean命名规则,如果你原有项目中存在按默认短类名注入Bean的代码,需要同步调整为全类名匹配。
内容的提问来源于stack exchange,提问作者mitali
相关产品推荐
相关产品推荐

