Reputation: 5921
So I have 2 Service classes that implement the same interface:
@Service
public class ServiceOne implements InterfaceOne {
}
@Service
public class ServiceTwo implements InterfaceOne {
}
I was wondering how I can inject particular instance inside the controller ?
@RestController
@RequestMapping("/test")
public class MyController {
@Inject
public MyController(InterfaceOne service) {
}
}
I'm not sure how DI is supposed to work with service classes. Basically those two services classes have the same interface and I was hoping to avoid nessesary if's if I could just inject the right one into the controller. An example would be much appreciated.
Edit: Sorry guys, I wasn't clear. What I also need to figure out is, which service class needs to be injected in the controller without specifying concrete implementation at that point. So, I was hoping there is a way to do some kind of if statement and check which implementation of the service should be plugged in.
Upvotes: 0
Views: 1241
Reputation: 15706
Two approaches when dealing with multiple implementations:
Use a specific flavour, identified by a @Qualifier
Annotate each implementation with a specific @Qualifier
(such as @Qualifier("One")
and @Qualifier("Two")
), and inject the specific flavour:
@Autowired
@Qualifier("One")
InterfaceOne implementation;
Use all implementations (or evaluate most appropriate with code)
The second approach is useful when you have a strategy interface, and want to have all implementations injected. You can then use all or any of them, and also query them for additional details.
In that case (when expecting 1..n implementations), use:
@Autowired
List<InterfaceOne> implementations;
If the implementations are optional (0..n), use:
@Autowired
Optional<List<InterfaceOne>> implementations;
EDIT: example on how to use a strategy interface with multiple implementations:
Interface:
public interface HelloWorldService {
String sayHello();
String getLanguage();
}
Implementations:
@Service
public class HelloWorldServiceEN implements HelloWorldService {
public String sayHello() { return "Hi there!"; }
public String getLanguage() { return "en"; }
}
@Service
public class HelloWorldServiceDE implements HelloWorldService {
public String sayHello() { return "Hallo!"; }
public String getLanguage() { return "de"; }
}
@Service
public class HelloWorldServiceFR implements HelloWorldService {
public String sayHello() { return "Salut!"; }
public String getLanguage() { return "fr"; }
}
Usage:
@Autowired
private List<HelloWorldService> helloWorldServices;
public void sayHelloInAllLanguages() {
for (HelloWorldService helloWorldService : helloWorldServices) {
System.out.println(helloWorldService.sayHello());
}
}
public void sayHelloInUserLanguage() {
String userLanguage = Locale.getDefault().getLanguage();
HelloWorldService helloWorldService = find(userLanguage);
System.out.println(helloWorldService.sayHello());
}
private HelloWorldService find(String language) {
// find service in specific language
Optional<HelloWorldService> service = helloWorldServices.stream().filter(s -> language.equals(s.getLanguage())).findFirst();
if (service.isPresent()) {
return service.get();
}
// fallback to english, if available
service = helloWorldServices.stream().filter(s -> language.equals("en")).findFirst();
if (service.isPresent()) {
return service.get();
}
// fallback to any language
return helloWorldServices.stream().findFirst().orElseThrow(IllegalStateException::new);
}
Upvotes: 3