Spring Boot中多实现接口的Bean注入方式及默认选择咨询
Great question! When you've got an interface like AccountService with dozens of implementations (40 in your case), Spring gives you clear, practical ways to inject the exact one you need, plus defined rules for which implementation gets picked by default. Let's break this down step by step.
How to Inject a Specific Implementation On Demand
Here are the most reliable approaches to target the implementation you want:
1. Use @Qualifier with Bean Names
Spring automatically assigns a default bean name to each implementation: it’s the class name with the first letter lowercase (e.g., defaultAccountServiceImpl for DefaultAccountServiceImpl). You can also customize the name using the value attribute in @Service (or @Component, @Repository).
To inject a specific implementation, pair @Autowired with @Qualifier and specify the bean name:
// Define your implementations @Service // Default bean name: defaultAccountServiceImpl public class DefaultAccountServiceImpl implements AccountService { // ... } @Service("specializedAccount") // Custom bean name public class SpecializedAccountServiceImpl implements AccountService { // ... } // Inject the specialized implementation @Autowired @Qualifier("specializedAccount") private AccountService accountService; // Or use constructor injection (preferred for immutability) private final AccountService accountService; public YourBusinessService(@Qualifier("defaultAccountServiceImpl") AccountService accountService) { this.accountService = accountService; }
2. Use @Resource for Name-Based Injection
If you prefer JSR-250 standard annotations over Spring-specific ones, @Resource works similarly by injecting beans by their name:
@Resource(name = "specializedAccount") private AccountService accountService;
3. Inject All Implementations for Dynamic Selection
For scenarios where you need to switch between implementations at runtime (e.g., based on a user’s role or request parameter), inject all implementations into a Map or List:
@Autowired private Map<String, AccountService> accountServiceMap; // Key = bean name, Value = implementation instance // Use in business logic public void handleAccountRequest(String serviceType) { AccountService selectedService = accountServiceMap.get(serviceType); if (selectedService == null) { throw new IllegalArgumentException("Invalid account service type: " + serviceType); } selectedService.processAccount(); }
Spring automatically populates this map with all AccountService beans, so no extra configuration is needed.
Which Implementation Gets Injected by Default?
If you just use @Autowired private AccountService accountService; without specifying a qualifier, Spring follows these rules:
If one implementation has
@Primary: Spring will prioritize that bean. This is perfect for setting a "default" implementation that’s used unless explicitly overridden.@Primary @Service public class DefaultAccountServiceImpl implements AccountService { // ... } @Service public class SpecializedAccountServiceImpl implements AccountService { // ... } // This injects DefaultAccountServiceImpl by default @Autowired private AccountService accountService;If there’s only one implementation: Spring will inject that single bean without any issues.
If multiple implementations exist with no
@Primary: Spring throws aNoUniqueBeanDefinitionException—it can’t decide which one to pick, so you must explicitly specify using one of the methods above.
内容的提问来源于stack exchange,提问作者Mithunkumar

