Spring中如何覆盖依赖@Component组件方法并动态切换两种实现
根因分析
你现在遇到的同时执行两个方法逻辑的问题,核心原因是Spring容器中同时存在两个MainClass类型的Bean:
- 第三方依赖自带的、标注了
@Component的原生MainClass实例 - 你自定义的、标注了
@Primary的OverMainClass实例@Primary仅能解决按类型注入时优先选择哪个Bean的问题,若代码中存在List<MainClass>/List<SomeThing>类型的批量注入、或者切面切中了所有SomeThing接口实现类的myMethod方法,就会触发两个实例的方法先后执行。
实现方案
步骤1:排除原生Bean的自动注册
首先在启动类的组件扫描规则中,排除第三方MainClass的自动注册,避免容器默认加载原生实例:
@SpringBootApplication @ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = MainClass.class )) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
步骤2:配置可切换的Bean注册规则
先移除OverMainClass上的@Component、@Primary注解:
public OverMainClass extends MainClass { @Override public void myMethod() { Logger.info(this, "second"); } }
新增配置类,通过@ConditionalOnProperty基于配置项控制注册哪个实例:
@Configuration public class MainClassConfig { // 配置项为true时注册自定义实现 @Bean @ConditionalOnProperty( name = "business.main-class.use-custom-impl", havingValue = "true", matchIfMissing = false ) public MainClass customMainClass() { return new OverMainClass(); } // 配置项为false时注册原生实现 @Bean @ConditionalOnProperty( name = "business.main-class.use-custom-impl", havingValue = "false", matchIfMissing = true ) public MainClass originalMainClass() { return new MainClass(); } }
步骤3:切换实现逻辑
只需要在application.yml/application.properties中修改配置项即可随时切换实现:
# 启用自定义实现,打印second business: main-class: use-custom-impl: true # 切回原生实现,打印first # business: # main-class: # use-custom-impl: false
该方案下容器同一时间只会存在一个MainClass类型的Bean,不会出现两个逻辑同时执行的问题,也不需要修改原有业务类的注入代码。
内容的提问来源于stack exchange,提问作者iftwMZ
相关产品推荐
相关产品推荐

