Spring 的自动装配(Autowiring)核心作用是减少手动配置依赖注入的代码量,让 Spring 容器自动识别并注入 Bean 之间的依赖关系,无需开发者在 XML 或注解中显式声明每一个依赖。下面我会通过「非自动装配(手动注入)」和「自动装配」的对比示例,清晰展示它是如何简化配置的。
一、先明确核心概念
自动装配的本质:Spring 容器根据指定的装配规则 (如按类型、按名称、按构造器等),自动为目标 Bean 注入其依赖的其他 Bean,无需手动通过 <property>(XML)或 @Autowired 显式指定(注:@Autowired 是触发自动装配的注解,本身是简化配置的核心)。
二、对比示例:手动注入 vs 自动装配
我们以一个简单的业务场景为例:UserService 依赖 UserDao,需要将 UserDao 注入到 UserService 中。
场景 1:XML 配置方式(最经典的对比)
1. 非自动装配(手动注入)
需要在 XML 中为 UserService 显式声明依赖的 UserDao,每一个依赖都要写 <property> 标签:
步骤 1:编写基础类
// UserDao 实现类
public class UserDaoImpl implements UserDao {
@Override
public void query() {
System.out.println("执行用户查询操作");
}
}
// UserService 业务类(依赖 UserDao)
public class UserService {
private UserDao userDao;
// 必须提供 set 方法,供 XML 手动注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.query();
}
}
步骤 2:XML 手动配置依赖
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义 UserDao Bean -->
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
<!-- 定义 UserService Bean,手动注入 UserDao -->
<bean id="userService" class="com.example.service.UserService">
<!-- 显式声明依赖:每一个依赖都要写这个标签 -->
<property name="userDao" ref="userDao"/>
</bean>
</beans>
2. 自动装配(XML 方式)
只需在 <bean> 标签中添加 autowire 属性,Spring 会自动匹配依赖,无需写 <property>:
基础类不变 (仍需保留 set 方法,因为默认按 byName/byType 装配需要 set 方法),XML 简化为:
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义 UserDao Bean -->
<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
<!-- 自动装配:autowire="byType" 按类型匹配依赖 -->
<bean id="userService" class="com.example.service.UserService" autowire="byType"/>
</beans>
可以看到:省去了 <property> 标签 ,如果 UserService 有多个依赖(如 OrderDao、LogDao),手动注入需要写多个 <property>,而自动装配只需一个 autowire 属性即可,简化效果随依赖数量增加更明显。
场景 2:注解配置方式(实际开发中最常用)
1. 非自动装配(手动注入,几乎没人用)
即使使用注解,若不开启自动装配,仍需手动指定依赖(比如用 @Bean 手动注入):
// 配置类
@Configuration
public class SpringConfig {
// 定义 UserDao Bean
@Bean
public UserDao userDao() {
return new UserDaoImpl();
}
// 手动注入 UserDao 到 UserService
@Bean
public UserService userService() {
UserService userService = new UserService();
// 手动调用 set 方法注入,每一个依赖都要写
userService.setUserDao(userDao());
return userService;
}
}
2. 自动装配(注解方式,核心简化)
使用 @Autowired 注解触发自动装配,无需手动调用 set 方法或声明依赖:
// 1. 开启组件扫描(让 Spring 识别 @Component 注解)
@Configuration
@ComponentScan("com.example")
public class SpringConfig {
// 无需手动定义 Bean 和注入,全部由自动装配完成
}
// 2. UserDao 标注为组件
@Component
public class UserDaoImpl implements UserDao {
@Override
public void query() {
System.out.println("执行用户查询操作");
}
}
// 3. UserService 标注为组件,并自动装配 UserDao
@Component
public class UserService {
// @Autowired 触发自动装配:Spring 自动找到 UserDao 类型的 Bean 注入
@Autowired
private UserDao userDao; // 甚至不需要 set 方法(Spring 通过反射直接注入字段)
public void getUser() {
userDao.query();
}
}
简化效果:
- 配置类中无需手动定义 Bean 和注入逻辑,只需开启组件扫描;
UserService中无需写 set 方法,只需一个@Autowired注解,Spring 自动完成依赖注入;- 若
UserService依赖多个 Bean(如UserDao、OrderDao),只需添加多个@Autowired注解,无需额外配置,手动注入则需要为每个依赖写注入代码。
三、自动装配的核心简化点总结
表格
| 配置方式 | 非自动装配(手动) | 自动装配 | 简化效果 |
|---|---|---|---|
| XML 配置 | 每个依赖都要写 <property> 标签 |
只需 autowire 属性,省去所有 <property> |
减少 XML 标签数量,配置更简洁 |
| 注解配置 | 手动调用 set 方法 / 构造器注入 | @Autowired 一键注入,无需手动操作 |
消除手动注入代码,代码更简洁 |
| 多依赖场景 | 依赖越多,配置 / 代码量线性增加 | 无论多少依赖,只需少量注解 / 配置 | 简化效果随依赖数量放大 |
四、自动装配的常用规则(补充)
Spring 自动装配支持 4 种规则(常用的是前两种):
byType(按类型):最常用,Spring 查找与依赖类型匹配的 Bean 注入(若同类型有多个 Bean,需用@Qualifier指定名称);byName(按名称):查找与依赖属性名相同的 Bean 注入(如userDao属性匹配id="userDao"的 Bean);constructor(按构造器):通过构造器注入,匹配构造器参数类型的 Bean;no(默认):关闭自动装配,需手动注入。
总结
- Spring 自动装配的核心简化逻辑:将「开发者手动声明依赖注入关系」的工作,交给 Spring 容器根据规则自动完成,消除了大量重复的注入配置 / 代码;
- XML 中通过
autowire属性省去<property>标签,注解中通过@Autowired省去手动调用 set / 构造器的注入代码; - 依赖越多,自动装配的简化效果越明显,这也是实际开发中几乎全用自动装配的核心原因。