spring-boot

How to inject parent or child class as component by ConditionalOnProperty annotation in spring boot


I have a interface:


public interface IBaseService {
    void say();
}

And a base class:

@Service
@ConditionalOnProperty(name = "startup",havingValue = "", matchIfMissing = true)
public class BaseServiceImpl implements IBaseService {
    @Override
    public void say() {

        System.out.println("default say");
    }
}

And two child classes:

//first
@Service
@ConditionalOnProperty(name = "startup",havingValue = "1")
public class CustomService1Impl extends BaseServiceImpl{
    @Override
    public void say() {
        System.out.println("custom 1");
    }

}
//second
@Service
@ConditionalOnProperty(name = "startup",havingValue = "2")
public class CustomService2Impl extends BaseServiceImpl{

    @Override
    public void say() {
        System.out.println("custom 2");
    }
}

when i set the startup prop in properties file

startup=

it will inject BaseServiceImpl. But when i use startup=1,the error whill come out like below: No qualifying bean of type 'com.example.service.IBaseService' available: expected single matching bean but found 2: baseServiceImpl,customService1Impl.

i want to inject child component by set startup=1 or startup=2. And inject parent componet by set startup= or not set this prop.


Solution

  • havingValue = "" is tricky because it will match all values except for false as described in docs.

    One possible solution is to use @ConditionalOnMissingBean for BaseServiceImpl in a @Configuration annotated class instead. We should remove both annotations from BaseServiceImpl, and create it like this

    @Configuration
    public class BaseServiceConfig {
    
        @Bean
        @ConditionalOnMissingBean(IBaseService.class)
        public BaseServiceImpl baseServiceImpl() {
            return new BaseServiceImpl();
        }
    }
    

    Any dependencies required for constructing BaseServiceImpl can be injected using method injection.