核心规则
Spring 处理数组 / 集合类注入时,会根据类型自动匹配并收集容器中的 Bean,具体规则如下:
- 数组:根据数组元素类型,在容器中查找所有匹配该类型的 Bean,组成数组注入
- Collection 接口及其实现类(如 List、Set):根据集合的泛型元素类型,收集所有匹配该类型的 Bean,封装成对应集合注入
- Map(key 为 String 类型):根据 Map 的 value 类型,收集所有匹配类型的 Bean,以 Bean 名称为 key、Bean 实例为 value 组成 Map 注入
代码示例
先定义一个支付处理器接口 PaymentHandler,以及多个实现类(支付宝、微信等):
public interface PaymentHandler {
void pay(); // 支付逻辑
}
// 支付宝实现
@Component
public class AlipayHandler implements PaymentHandler {
@Override
public void pay() { System.out.println("支付宝支付"); }
}
// 微信支付实现
@Component
public class WechatHandler implements PaymentHandler {
@Override
public void pay() { System.out.println("微信支付"); }
}
注入数组
@Service
public class ArrayService {
// 注入所有 PaymentHandler 类型的 Bean ,组成数组
@Autowired
private PaymentHandler[] paymentHandlers;
public void testArray() {
System.out.println("=== 数组注入测试 ===");
for (PaymentHandler p : paymentHandlers) {
p.pay();
}
}
}
注入 List/Set
如果不需要通过 key 定位,而是要遍历所有实现类(例如执行批量操作、责任链模式),可以用这个
@Service
public class ListAndSetService {
// 注入所有 PaymentHandler 类型的 Bean 到 List(有序,可通过@Order控制)
@Autowired
private List<PaymentHandler> paymentHandlerList;
// 注入所有 PaymentHandler 类型的 Bean 到 Set(无序,元素唯一)
@Autowired
private Set<PaymentHandler> paymentHandlerSet;
public void testCollection() {
System.out.println("\n=== List注入测试 ===");
paymentHandlerList.forEach(PaymentHandler::pay);
System.out.println("\n=== Set注入测试 ===");
paymentHandlerSet.forEach(paymentHandler -> paymentHandler.pay());
}
}
如果需要 List 中的 Bean 按指定顺序排列,可以在实现类上添加 @Order 注解:
@Component
@Order(2) // 数字越小,优先级越高
public class AlipayHandler implements PaymentHandler { ... }
@Component
@Order(1)
public class WechatHandler implements PaymentHandler { ... }
注入 Map
@Service
public class MapService {
// 注入所有 PaymentHandler 类型的 Bean 到 Map(key=Bean名称,value=Bean实例)
@Autowired
private Map<String, PaymentHandler> paymentHandlerMap;
public void testMap() {
System.out.println("\n=== Map注入测试 ===");
paymentHandlerMap.forEach((beanName, paymentHandler) -> {
System.out.print("[" + beanName + "] ");
paymentHandler.pay();
});
}
}
测试代码
启动类的方法改成这样
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(J20250721Application.class, args);
//测试数组
ArrayService arrayService = context.getBean(ArrayService.class);
arrayService.testArray();
//测试Collection
ListAndSetService listAndSetService = context.getBean(ListAndSetService.class);
listAndSetService.testCollection();
//测试Map
MapService mapService = context.getBean(MapService.class);
mapService.testMap();
}