@Autowired 到底按什么找 Bean?两个同类型的 Bean 怎么选?构造器注入、setter 注入、字段注入有什么不同?没有候选时会怎样?这篇在 Spring Framework 7.0.9 上把各种写法和候选解析的结果逐个跑出来。
容器里:构造器注入 d 非 null;setter 注入 d 非 null;字段注入 d 非 null 脱离容器直接 new:new Setter() → d=null;new Field() → d=null;Ctor 没有无参构造器,必须把 Dep 传进去才能 new,所以不会出现“忘了注入”
构造器注入强制传参,setter 与字段注入 new 出来是 null;容器里三种都能注入。
(a) 两个 Pay,按类型注入,没有任何提示:
NoHint → NoUniqueBeanDefinitionException: No qualifying bean of type 'Pay' available: expected single matching bean but found 2: alipay,wechat
(b) 参数名等于 Bean 名(需要 javac -parameters,本实验已加):
参数名 alipay → alipay
(c) @Qualifier:
@Qualifier("wechat") → wechat
(d) List<Pay> 与 Map<String,Pay>:
List<Pay> → [alipay, wechat];Map<String,Pay> 的键 → [alipay, wechat]
(e) @Primary:
@Primary(wechat 标了) → wechat
(f) 两个都是 @Primary:
TwoPrimary → NoUniqueBeanDefinitionException: No qualifying bean of type 'Pay' available: more than one 'primary' bean found among candidates: [alipay, wechat]
(g) @Order(2) 的 alipay 与 @Order(1) 的 wechat:
List<Pay> → [wechat, alipay];Map<String,Pay> 的键 → [alipay, wechat]
(h) @Priority:
@Priority(1) 的 alipay vs @Priority(5) 的 wechat,按类型注入 → alipay按类型找到多个时失败,参数名、@Qualifier、@Primary、@Priority 能选出一个,两个 @Primary 仍冲突。
(a) 构造器参数 Pay,没有任何候选:
NeedsPay → NoSuchBeanDefinitionException: No qualifying bean of type 'Pay' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
(b) 参数 List<Pay>,没有任何候选:
List<Pay> 没有候选 → size=0
(c) Optional / ObjectProvider / required=false:
Optional<Pay> → isPresent=false;ObjectProvider.getIfAvailable → null
字段 p=null必需的单个依赖直接失败,集合依赖是空集合,可选依赖可以写成 Optional、ObjectProvider 或 required=false。
Repo<Integer> → Integer 仓库;Repo<String> → String 仓库
泛型参数参与候选匹配,不需要 @Qualifier。