Assume that you have a GreetingService
public interface GreetingService {
void doGreetings();
}
And you have 2 implementations HelloService
@Service
@Slf4j
public class HelloService implements GreetingService{
@Override
public void doGreetings() {
log.info("Hello world!");
}
}
and HiService
@Slf4j
@Service
public class HiService implements GreetingService{
@Override
public void doGreetings() {
log.info("Hi world!");
}
}
Then you have another interface, which is BusinessService
to call some business
public interface BusinessService {
void doGreetings();
}
There are some ways to do that
#1. Use @Autowired
@Component
public class BusinessServiceImpl implements BusinessService{
@Autowired
private GreetingService hiService; // Spring automatically maps the name for you, if you don't want to change it.
@Autowired
private GreetingService helloService;
@Override
public void doGreetings() {
hiService.doGreetings();
helloService.doGreetings();
}
}
In case you need to change your implementation bean name, refer to other answers, by setting the name to your bean, for example @Service("myCustomName")
and applying @Qualifier("myCustomName")
#2. You can also use constructor injection
@Component
public class BusinessServiceImpl implements BusinessService {
private final GreetingService hiService;
private final GreetingService helloService;
public BusinessServiceImpl(GreetingService hiService, GreetingService helloService) {
this.hiService = hiService;
this.helloService = helloService;
}
@Override
public void doGreetings() {
hiService.doGreetings();
helloService.doGreetings();
}
}
This can be
public BusinessServiceImpl(@Qualifier("hiService") GreetingService hiService, @Qualifier("helloService") GreetingService helloService)
But I am using Spring Boot 2.6.5
and
public BusinessServiceImpl(GreetingService hiService, GreetingService helloService)
is working fine, since Spring automatically get the names for us.
#3. You can also use Map
for this
@Component
@RequiredArgsConstructor
public class BusinessServiceImpl implements BusinessService {
private final Map<String, GreetingService> servicesMap; // Spring automatically get the bean name as key
@Override
public void doGreetings() {
servicesMap.get("hiService").doGreetings();
servicesMap.get("helloService").doGreetings();
}
}
List
also works fine if you run all the services. But there is a case that you want to get some specific implementation, you need to define a name for it or something like that. My reference is here
For this one, I use @RequiredArgsConstructor
from Lombok.