Are you looking for a flexible way to choose between multiple service implementations in your Spring Boot application? In this tutorial, we’ll show you how to use Map injection to dynamically select and invoke Spring beans based on user input. This approach is perfect for scenarios where you have multiple strategies or services, such as sending messages via email or SMS.
What You’ll Learn
How to define a common interface for your services
How to implement multiple beans with custom names
How to inject all beans as a Map in your controller
How to select and use a service dynamically based on a request parameter
1. Define a Common Interface
First, create an interface that all your message services will implement:
MessageService.java
public interface MessageService {
void sendMessage(String message);
}
2. Implement Multiple Services with Custom Bean Names
Use the @Service("beanName")
 annotation to give each service a unique name. This name will be used as the key in the injected Map.
EmailService.java
import org.springframework.stereotype.Service;
@Service("emailService")
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("Email sent: " + message);
}
}
SMSService.java
import org.springframework.stereotype.Service;
@Service("smsService")
public class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("SMS sent: " + message);
}
}
3. Inject All Beans as a Map in Your Controller
Spring Boot allows you to inject all beans of a certain type as a Map<String, BeanType>
. The key is the bean name, and the value is the bean instance.
MessageController.java
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/message")
public class MessageController {
private final Map messageServiceMap;
public MessageController(Map messageServiceMap) {
this.messageServiceMap = messageServiceMap;
}
@GetMapping("/send")
public String sendMessage(@RequestParam String type, @RequestParam String msg) {
MessageService service = messageServiceMap.get(type);
if (service != null) {
service.sendMessage(msg);
return "Message sent via: " + type;
} else {
return "Service not found for type: " + type;
}
}
}
4. Example API Calls
Try these API calls to see dynamic bean selection in action:
Send Email:
GET /api/message/send?type=emailService&msg=Hello
Output:
Email sent: Hello
Send SMS:
GET /api/message/send?type=smsService&msg=Hello
Output:
SMS sent: Hello
Why Use Map Injection in Spring?
Â
Flexibility:Â Add new message services (e.g., Push Notification) without changing controller logic.
Maintainability:Â Decouple service selection from your controller logic.
Scalability:Â Easily support many strategies or implementations.
Conclusion
Map injection in Spring Boot is a powerful technique for building flexible and maintainable applications. By injecting all beans of a certain type as a Map, you can easily select the right implementation at runtime based on user input or other criteria. Try this pattern in your next project to simplify your code and support more features with less effort!
Ready to level up your Spring Boot skills? Try this pattern in your next project and share your experience in the comments below!