Spring Boot中如何通过ConditionalOnProperty注解条件注入父/子类组件
问题分析
当配置startup=1时出现bean冲突,是因为BaseServiceImpl的条件注解没有正确排除startup为1或2的场景,导致父类和对应子类的bean同时被Spring实例化,容器中存在多个IBaseService类型的bean,无法确定注入哪个。
解决方案
以下三种方案都能实现需求,按需选择:
方案一:用@ConditionalOnExpression精准控制父类bean的创建时机
修改BaseServiceImpl的注解,让它仅在startup为空、不存在或非1/2值时被创建:
@Service @ConditionalOnExpression("${startup:} != '1' && ${startup:} != '2'") public class BaseServiceImpl implements IBaseService { @Override public void say() { System.out.println("default say"); } }
两个子类保持原有注解不变:
@Service @ConditionalOnProperty(name = "startup", havingValue = "1") public class CustomService1Impl extends BaseServiceImpl{ @Override public void say() { System.out.println("custom 1"); } } @Service @ConditionalOnProperty(name = "startup", havingValue = "2") public class CustomService2Impl extends BaseServiceImpl{ @Override public void say() { System.out.println("custom 2"); } }
方案二:用@ConditionalOnMissingBean避免父类与子类bean共存
给BaseServiceImpl添加@ConditionalOnMissingBean注解,确保当有其他IBaseService实现类的bean存在时,父类bean不被实例化:
@Service @ConditionalOnProperty(name = "startup", havingValue = "", matchIfMissing = true) @ConditionalOnMissingBean(IBaseService.class) public class BaseServiceImpl implements IBaseService { @Override public void say() { System.out.println("default say"); } }
子类注解保持不变,这样当startup=1或2时,对应子类bean被创建,BaseServiceImpl会因已有同类型bean而不被实例化。
方案三:自定义Condition类实现灵活判断
创建自定义Condition类,判断startup的值是否为1或2:
public class StartupNot1Or2Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String startupValue = context.getEnvironment().getProperty("startup"); return startupValue == null || startupValue.isEmpty() || (!"1".equals(startupValue) && !"2".equals(startupValue)); } }
给BaseServiceImpl添加@Conditional注解关联自定义条件:
@Service @Conditional(StartupNot1Or2Condition.class) public class BaseServiceImpl implements IBaseService { @Override public void say() { System.out.println("default say"); } }
子类保持原有配置即可。
验证效果
- 不配置
startup或配置startup=时,仅BaseServiceImpl被注入; - 配置
startup=1时,仅CustomService1Impl被注入; - 配置
startup=2时,仅CustomService2Impl被注入; - 配置
startup为其他值(如3)时,仅BaseServiceImpl被注入。
内容的提问来源于stack exchange,提问作者navizal
相关产品推荐
相关产品推荐

