依赖注入的自动装配(Autowiring)学习笔记
一、自动装配的本质与价值
概念:自动装配(Autowiring)是 Spring 容器根据类型或名称自动为 Bean 注入依赖的机制,减少手动配置的工作量。
生活案例:餐厅厨师需要锅和铲子,传统方式需手动领取(手动配置),自动装配则像厨房管理员根据厨师技能自动分配工具(根据类型 / 名称匹配)。
核心价值:
- 减少冗余配置:无需在 XML 或 JavaConfig 中显式声明依赖关系。
- 动态适配:运行时根据上下文自动选择合适的实现。
- 适应变化:新增依赖时无需修改现有代码,提升扩展性。
二、自动装配的五种方式
1. byType(按类型装配)
原理:容器查找与目标属性类型匹配的 Bean 进行注入。
案例:咖啡店需要咖啡机(类型为 CoffeeMachine),容器自动提供美式咖啡机(AmericanCoffeeMachine)。
代码示例:
// XML配置
<bean id="coffeeMachine" class="com.example.AmericanCoffeeMachine"/>
<bean id="barista" class="com.example.Barista" autowire="byType"/>
// Java代码
public class Barista {
private CoffeeMachine coffeeMachine; // 自动匹配类型为CoffeeMachine的Bean
}
特点:
- 优点:简单高效,适合单一实现的场景。
- 缺点:存在多个同类型 Bean 时会抛出异常。
2. byName(按名称装配)
原理:容器查找与目标属性名称匹配的 Bean(首字母小写)。
案例:餐厅服务员需要 "mainDish",容器自动分配名称为 "mainDish" 的菜品。
代码示例:
// XML配置
<bean id="mainDish" class="com.example.Pasta"/>
<bean id="waiter" class="com.example.Waiter" autowire="byName"/>
// Java代码
public class Waiter {
private Dish mainDish; // 自动匹配id为"mainDish"的Bean
}
特点:
- 优点:明确指定依赖名称,避免类型歧义。
- 缺点:依赖 Bean 的命名需严格规范。
3. constructor(构造器自动装配)
原理:根据构造器参数类型匹配 Bean。
案例:蛋糕店需要烤箱和搅拌器,容器自动选择匹配构造器参数的 Bean。
代码示例:
// XML配置
<bean id="oven" class="com.example.ElectricOven"/>
<bean id="mixer" class="com.example.HandMixer"/>
<bean id="baker" class="com.example.Baker" autowire="constructor"/>
// Java代码
public class Baker {
private final Oven oven;
private final Mixer mixer;
public Baker(Oven oven, Mixer mixer) { // 自动匹配参数类型
this.oven = oven;
this.mixer = mixer;
}
}
特点:
- 优点:确保依赖初始化完成后才创建对象。
- 缺点:构造器参数顺序和类型需与容器中的 Bean 严格匹配。
4. autodetect(自动检测)
原理:优先尝试构造器装配,失败则使用 byType。
案例:奶茶店员工需要制冰机(IceMaker),容器先尝试构造器装配,若无匹配则按类型装配。
适用场景:混合使用构造器和属性注入的复杂场景。
5. no(默认方式)
原理:不启用自动装配,需手动配置依赖。
案例:手工定制西装,需精确指定每颗纽扣的位置(手动配置)。
三、@Autowired 注解的深度解析
本质:Spring 提供的注解,默认实现 byType 自动装配。
生活案例:外卖员需要电动车(依赖),系统自动分配符合其驾照类型的电动车。
核心用法:
- 字段注入:
@Component public class DeliveryMan { @Autowired private ElectricBike bike; // 自动注入类型为ElectricBike的Bean } - 构造器注入(推荐):
@Component public class Chef { private final Knife knife; @Autowired public Chef(Knife knife) { // 自动匹配构造器参数 this.knife = knife; } } - 方法注入:
@Component public class Barista { private CoffeeMachine machine; @Autowired public void setMachine(CoffeeMachine machine) { // 自动注入到setter方法 this.machine = machine; } }
解决歧义:
- @Qualifier:指定 Bean 名称:
@Autowired @Qualifier("italianCoffeeMachine") private CoffeeMachine machine; - @Primary:标记首选 Bean:
@Primary @Bean public CoffeeMachine americanCoffeeMachine() { return new AmericanCoffeeMachine(); }
四、自动装配的生命周期管理
流程示例:
- 实例化 Bean:创建对象。
- 自动装配依赖:根据类型 / 名称注入属性。
- 调用初始化方法(如 @PostConstruct)。
注意事项:
- 循环依赖:A→B→A 会导致 Spring 抛出异常,需通过 @Lazy 或调整设计解决。
- 可选依赖:使用 @Autowired (required = false) 允许依赖为 null。
五、最佳实践与避坑指南
- 优先使用构造器注入:确保依赖不可变,避免空指针。
- 合理命名 Bean:byName 方式依赖规范的命名。
- 明确处理歧义:使用 @Qualifier 或 @Primary 消除多候选 Bean 的问题。
- 避免过度使用自动装配:复杂依赖关系建议显式配置。


994

被折叠的 条评论
为什么被折叠?



