全面解析 Spring 依赖注入:@Autowired、@Inject 与 @Resource 深度剖析
在 Spring 框架中,依赖注入(Dependency Injection,简称 DI)是核心功能之一。通过不同的注解(如 @Autowired、@Inject、@Resource),开发者可以以声明式方式将所需组件引入到业务代码中,解耦模块间的依赖关系。本文将从注解来源、默认注入行为,到底层处理流程以及多候选 Bean 的决策机制,全面剖析 Spring 容器如何解析并注入这些注解。
使用场景
假设我们有一个 Vehicle 接口,以及它的两个实现类 Car 和 Bus:
public interface Vehicle {}
@Component
public class Car implements Vehicle {}
@Component
public class Bus implements Vehicle {}
另有一个 VehicleService 类,需要注入一个 Vehicle 类型的 Bean。下面展示三种常用的注解方式:
1. @Autowired + @Qualifier
@Component
public class VehicleService {@Autowired@Qualifier("car")  // 指定注入名称为 car 的 Beanprivate Vehicle vehicle;
}
2. @Inject + @Qualifier/@Named
@Component
public class VehicleService {@Inject@Qualifier("car")private Vehicle vehicle;@Inject@Named("bus")  // 等同于 @Qualifierprivate Vehicle anotherVehicle;
}
3. @Resource
@Component
public class VehicleService {@Resource(name = "car")private Vehicle vehicle;
}
尽管三者都能完成注入,但它们在规范归属与底层实现上各有差异。
注解来源与默认行为
-  JSR 250( jakarta.annotation-api)- 包含:@Resource、@PostConstruct、@PreDestroy等。
- 默认按 名称 注入。
 
- 包含:
-  JSR 330( jakarta.inject-api)- 包含:@Inject、@Qualifier、@Named。
- 默认按 类型 注入,可配合 @Qualifier/@Named实现名称注入。
 
- 包含:
-  Spring 自有注解 - 包含:@Autowired、@Qualifier。
- 默认按 类型 注入,可与 @Qualifier搭配,指定名称。
 
- 包含:
注入流程一览
Spring 在创建 Bean 时,会依次执行:
- 实例化 (createBeanInstance)
- 属性填充(populateBean)
- 初始化(initializeBean)
属性填充阶段会触发所有已注册的 InstantiationAwareBeanPostProcessor,其中:
- CommonAnnotationBeanPostProcessor处理- @Resource
- AutowiredAnnotationBeanPostProcessor处理- @Autowired和- @Inject
在 populateBean(...) 中,Spring 遍历这些后置处理器并调用其 postProcessProperties(...) 方法,为被注解的字段或 setter 提供目标依赖。
后置处理器注册时机
在 AbstractApplicationContext#refresh() 中,会先执行:
registerBeanPostProcessors(beanFactory)
finishBeanFactoryInitialization(beanFactory)
- registerBeanPostProcessors通过- PostProcessorRegistrationDelegate收集并实例化所有- BeanPostProcessor。
- 这样,处理自动注入的后置处理器就已就绪,后续创建业务 Bean 时可正常进行注入。
深入剖析:@Resource 注入机制
- 扫描注解:CommonAnnotationBeanPostProcessor在静态块中加载@Resource类型。
- 定位字段:buildResourceMetadata(Class<?>)通过反射遍历所有字段,收集带注解的成员。
- 执行注入:postProcessProperties(...)调用InjectionMetadata.inject(...),依次为每个ResourceElement设置字段值。
- 匹配逻辑: - 优先按 name 查找 Bean
- 若未找到且允许回退,则按 type 匹配(走 Spring 的类型解析机制)
 
深入剖析:@Autowired / @Inject 注入机制
- 初始化注解类型:AutowiredAnnotationBeanPostProcessor构造函数中加载@Autowired、@Value、@Inject。
- 定位字段:buildAutowiringMetadata(Class<?>)反射扫描所有字段,收集AutowiredFieldElement。
- 执行注入:在 postProcessProperties(...)中,调用InjectionMetadata.inject(...),反射赋值。
- 优先匹配: - 若 descriptor.usesStandardBeanLookup(),会先通过名称获取(若存在)
- 否则再按类型查找(调用 DefaultListableBeanFactory.doResolveDependency)
 
- 若 
多候选 Bean 的决策策略
当按类型匹配到多个 Bean 时,Spring 会依次考虑:
- @Primary 标注的 Bean
- 与 依赖名称 相同的 Bean
- 与 @Qualifier/@Named 指定名称一致的 Bean
- @Priority(值越小优先级越高)
- 自定义注册(resolvableDependencies)
若都无法唯一识别,则抛出 NoUniqueBeanDefinitionException(或对非必须注入返回空)。
小结
- 三类注解来源不同,默认注入行为也有细微差异。
- Spring 通过两大后置处理器对注解进行解析和注入。
- 注入前后处理器在容器刷新时完成注册,确保业务 Bean 创建时即可使用。
- 多 Bean 场景下,Spring 提供完善的优先级策略,保证依赖可预测地注入。
