Spring 实现自动装配(Autowiring)的核心原理是 IoC 容器基于类型或名称匹配,通过反射机制动态解析并注入依赖对象。其本质是 控制反转(IoC) 的具体实践,将依赖关系的维护从代码中剥离,交由 Spring 容器统一管理。
01-自动装配的核心原理
1.1 依赖解析机制
-
类型匹配:容器根据目标 Bean 的依赖类型(如 UserService中的 UserRepository字段类型),在容器中查找匹配的 Bean;
-
名称匹配:若开启 byName模式,则根据 字段名 / 参数名 查找同名的 Bean;
-
注解驱动:@Autowired等注解 触发容器按类型扫描依赖。
1.2 反射注入
通过 Java 反射 API(Class.getDeclaredField(), Method.invoke())动态设置字段值或调用 Setter 方法
伪代码示例:
Field field = target.getClass().getDeclaredField("userRepo");
field.setAccessible(true);
field.set(target, beanFactory.getBean(UserRepository.class)); // 注入依赖
1.3 循环依赖处理
三层缓存机制(仅限单例Bean):
- singletonObjects:完整 Bean 缓存;
- earlySingletonObjects:提前暴露的不完整 Bean;
- singletonFactories:生成早期 Bean 的工厂
构造器注入的循环依赖无法解决(会抛异常)
想详细了解循环依赖可以看下这篇文章:一文详解Spring Bean的循环依赖问题及解决方案(三级缓存)-CSDN博客
02-Spring 实现自动装配的方式
2.1 XML 配置
传统方式,现在已经很少使用
<!– 全局启用 byType 自动装配 –>
<beans default-autowire="byType">
<bean id="userService" class="com.example.UserService"/>
<bean id="userRepo" class="com.example.UserRepositoryImpl"/> <!– 按类型匹配 –>
</beans>
<!– 单个 Bean 指定构造器注入 –>
<bean id="orderService" class="com.example.OrderService" autowire="constructor"/>
2.2 注解驱动(主流)
01-@Autowired 注解(Spring 原生)
按类型自动装配,可配合 @Qualifier指定 Bean 名称,支持 required = false(可选依赖,不存在时不注入)
1.1 字段注入
@Service
public class UserService {
@Autowired // 自动注入
private UserRepository userRepository;
@Autowired
private EmailService emailService;
public void registerUser(String username) {
userRepository.save(username);
emailService.sendWelcomeEmail(username);
}
}
@Repository
public class UserRepository {
public void save(String user) {
System.out.println("保存用户: " + user);
}
}
@Service
public class EmailService {
public void sendWelcomeEmail(String user) {
System.out.println("发送欢迎邮件给: " + user);
}
}
1.2 构造器注入(推荐)
@Service
public class OrderService {
private final PaymentService paymentService;
private final InventoryService inventoryService;
@Autowired // Spring 4.3+ 可省略
public OrderService(PaymentService paymentService,
InventoryService inventoryService) {
this.paymentService = paymentService;
this.inventoryService = inventoryService;
}
public void processOrder(Order order) {
// 使用注入的服务
}
}
1.3 Setter 方法注入
@Service
public class ProductService {
private DiscountService discountService;
private TaxCalculator taxCalculator;
@Autowired
public void setDiscountService(DiscountService discountService) {
this.discountService = discountService;
}
@Autowired
public void setTaxCalculator(TaxCalculator taxCalculator) {
this.taxCalculator = taxCalculator;
}
}
02-@Resource(JSR-250)
默认按名称装配,其次按类型
import javax.annotation.Resource;
@Service
public class ShoppingCartService {
@Resource // 按名称注入,等价于 @Autowired + @Qualifier
private ProductRepository productRepository;
@Resource(name = "creditCardPayment") // 指定bean名称
private PaymentProcessor paymentProcessor;
@Resource(type = OrderValidator.class) // 按类型注入
private OrderValidator orderValidator;
}
03-@Inject(JSR-330)
类似 @Autowired,需额外依赖 @Named 注解指定名称
import javax.inject.Inject;
import javax.inject.Named;
@Component
public class ReportGenerator {
@Inject // 与 @Autowired 功能相似
private DataSource dataSource;
@Inject
@Named("pdfFormatter") // 指定bean名称
private ReportFormatter pdfFormatter;
@Inject
public ReportGenerator(@Named("excelFormatter") ReportFormatter formatter) {
this.excelFormatter = formatter;
}
}
2.3 Java Config 配置
相当于传统Spring中的XML配置文件
@Configuration
public class AppConfig {
@Bean
public UserService userService(UserRepository userRepo) { // 参数自动注入
return new UserService(userRepo);
}
@Bean
public UserRepository mysqlRepo() {
return new MysqlUserRepository();
}
}
03-核心流程详解
3.1 容器启动
1. 加载配置元数据(XML / 注解 / Java Config);
2. 解析 Bean 定义,注册到 DefaultListableBeanFactory
3.2 依赖收集
扫描每个 Bean 的依赖描述符(如 @Autowired字段、构造器参数)
3.3 依赖注入
步骤 1:根据类型查找候选 Bean(从 BeanFactory中检索);
步骤 2:处理歧义性(使用 @Primary或 @Qualifier);
步骤 3:通过反射注入依赖(字段 / 构造器 / Setter)
3.4 生命周期回调
注入后执行 @PostConstruct / InitializingBean.afterPropertiesSet() —> 初始化Bean时调用
04-使用建议
优先使用 构造器注入(不可变依赖、易测试);
避免字段注入(不利于测试和封装)




