Spring中如何通过别名从自动注入的Bean Map中获取正确实例
问题原因
Spring 自动注入的Map<String, 对应Bean类型>结构,默认只会将每个Bean的主名称作为Map的key,Bean的别名仅存储在BeanDefinition的别名列表中,不会被自动填充到该Map的key集合里,因此只有主名称能直接从注入的Map中获取到实例。
而@Qualifier注解可以匹配到别名,是因为Spring在处理依赖注入的名称匹配逻辑时,会同时检索Bean的主名称和所有别名,所以能正常拿到实例。
可行解决方案
- 方案1:手动构建包含所有别名的全局服务Map
你可以通过ApplicationContext主动读取每个PolicyDetailsService实现类的所有别名,自行组装包含所有主名称、别名的Map并注册为Bean,后续直接注入该Map即可。
示例代码:
@Configuration public class PolicyDetailsServiceConfig { @Bean public Map<String, PolicyDetailsService> policyDetailsServiceMap(ApplicationContext context) { Map<String, PolicyDetailsService> fullServiceMap = new HashMap<>(); // 先获取该类型所有主名称对应的实例 Map<String, PolicyDetailsService> primaryServiceMap = context.getBeansOfType(PolicyDetailsService.class); primaryServiceMap.forEach((primaryName, serviceInstance) -> { // 存入主名称 fullServiceMap.put(primaryName, serviceInstance); // 遍历该Bean的所有别名,全部存入Map String[] aliases = context.getAliases(primaryName); for (String alias : aliases) { fullServiceMap.put(alias, serviceInstance); } }); return fullServiceMap; } }
注入时直接使用该自定义Map即可:
@Autowired private Map<String, PolicyDetailsService> policyDetailsServiceMap;
- 方案2:为每个名称单独注册同实例Bean
如果别名数量不多,可以给同一个实现类的每个名称单独注册Bean,所有Bean方法返回同一个实例,这样Spring自动注入的Map就会自动包含所有名称作为key。
示例代码:
@Configuration public class PolicyDetailsServiceConfig { // 注册基础实例 @Bean public PolicyDetailsService policyDetailsService() { return new PolicyDetailsServiceImpl(); } // 每个别名单独注册Bean,指向同一个实例 @Bean("AGENCY-PLI") public PolicyDetailsService agencyPliService() { return policyDetailsService(); } @Bean("AGENCY-PMM") public PolicyDetailsService agencyPmmService() { return policyDetailsService(); } }
- 方案3:直接通过ApplicationContext查询实例
不需要注入Map,直接注入ApplicationContext,调用getBean方法时传入名称即可,该方法本身支持别名匹配。
示例代码:
@Autowired private ApplicationContext context; // 调用处代码 public void test(String policyType) { PolicyDetailsService service = context.getBean(policyType, PolicyDetailsService.class); service.xxx(); }
内容的提问来源于stack exchange,提问作者Pallab
相关产品推荐
相关产品推荐

