Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring choose bean implementation at runtime

I'm using Spring Beans with annotations and I need to choose different implementation at runtime.

@Service public class MyService {    public void test(){...} } 

For example for windows's platform I need MyServiceWin extending MyService, for linux platform I need MyServiceLnx extending MyService.

For now I know only one horrible solution:

@Service public class MyService {      private MyService impl;     @PostInit    public void init(){         if(windows) impl=new MyServiceWin();         else impl=new MyServiceLnx();    }     public void test(){         impl.test();    } } 

Please consider that I'm using annotation only and not XML config.

like image 557
Tobia Avatar asked Dec 18 '15 07:12

Tobia


People also ask

How does Spring know which bean to inject?

In Spring Boot, we can use Spring Framework to define our beans and their dependency injection. The @ComponentScan annotation is used to find beans and the corresponding injected with @Autowired annotation. If you followed the Spring Boot typical layout, no need to specify any arguments for @ComponentScan annotation.

Can we use @qualifier and @bean together?

By using the @Qualifier annotation, we can eliminate the issue of which bean needs to be injected. By including the @Qualifier annotation, together with the name of the specific implementation we want to use, in this example Foo, we can avoid ambiguity when Spring finds multiple beans of the same type.


1 Answers

1. Implement a custom Condition

public class LinuxCondition implements Condition {   @Override   public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {     return context.getEnvironment().getProperty("os.name").contains("Linux");  } } 

Same for Windows.

2. Use @Conditional in your Configuration class

@Configuration public class MyConfiguration {    @Bean    @Conditional(LinuxCondition.class)    public MyService getMyLinuxService() {       return new LinuxService();    }     @Bean    @Conditional(WindowsCondition.class)    public MyService getMyWindowsService() {       return new WindowsService();    } } 

3. Use @Autowired as usual

@Service public class SomeOtherServiceUsingMyService {      @Autowired         private MyService impl;      // ...  } 
like image 94
nobeh Avatar answered Oct 05 '22 06:10

nobeh