自动注入相关注解
@Autowired
在使用Spring进行项目开发的时候,会大量使用到自动装配,那自动装配是什么呢?简单来说:Spring 利用依赖注入(DI)功能,完成SpringIOC容器中各个组件之间的依赖关系赋值管理。
@Autowired
是一个Spring框架的原生注解,它可以对类成员变量、方法及构造函数进行标注,让
spring 完成 bean 自动装配的工作,是 Spring
框架中用于实现依赖注入(Dependency Injection, DI)
的关键注解
- 自动将容器中已创建的 Bean 注入到当前 Bean 的字段、构造方法或
setter
方法中 - 避免手动创建对象,实现松耦合的组件协作
- 遵循 “控制反转(IoC)” 原则,让容器管理对象生命周期
使用@Autowired
时候,容器启动的扫描流程如下:
- Spring容器在启动时会自动扫描并管理所有带有
@Component
、@Service
、@Repository
和@Controller
等注解的类 @Autowired
通过类型匹配(byType
)在容器中查找对应的 Bean,自动将匹配的bean注入到指定的位置。
默认情况下,Spring 按类型解析 @Autowired
依赖。如果容器中存在多个相同类型的
Bean,框架将抛出异常。要解决这一冲突,需要明确告诉 Spring 要注入哪个
Bean。
1 | public interface PaymentService { ... } |
此时可以通过@Qualifier
进行指定名称去装配
bean,它会检查容器,并查找与要自动装配的属性名称完全相同的 Bean
来进行装配,但是也可通过 @Service("自定义名称")
指定)。
1 |
|
而且还可以给 Bean 添加 @Primary
注解,标记其中一个作为默认首选。但是在@Qualifier
存在情况下会强制指定特定
Bean,优先级高于 @Primary
。
1 |
|
注意与@Primary
和
@Profile
的区别
1 |
|
@Autowired
包含两个重要参数:
required
(默认true
):指定依赖是否必须存在。若为
false
,当容器中没有匹配的 Bean 时,注入null
而不抛出异常1
2
private UserRepository userRepository; // 允许为 null与
@Qualifier
配合使用: 当存在多个同类型 Bean 时,通过@Qualifier
指定要注入的 Bean 的名称。
@Autowired
可以标注在三个位置,功能等价但使用场景不同:
字段注入
在 Bean 实例化后立即注入
使用
@Autowired
对属性进行注解。这样就不需要使用Getter
和Setter
了1
2
3
4
5
6
public class UserService {
private UserRepository userRepository; // 自动注入Repository
// ...业务逻辑
}构造方法注入
在 Bean 创建时注入(推荐用于必填依赖)
1
2
3
4
5
6
7
8
9
10
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
// ...
}Spring 4.3 + 后,若构造方法唯一,@Autowired 可省略
Setter 方法注入(支持可选依赖)
在 Bean 初始化阶段注入
1
2
3
4
5
6
7
8
9
10
public class LogService {
private LogRepository logRepository;
// 设置为可选依赖
public void setLogRepository(LogRepository logRepository) {
this.logRepository = logRepository;
}
// ...
}
在构建 Bean 时,@Autowired
依赖应该可用。否则,如果
Spring 无法解析用于装配的 Bean,它就会阻止 Spring 容器成功启动,并抛出
NoSuchBeanDefinitionException
异常
@Resource
@Resource 是 Java EE(现 Jakarta EE)标准中的依赖注入注解(JSR-250 规范),从 Java 6 开始引入。它的主要作用是将一个资源(Resource)注入到目标对象中,用于描述依赖注入(Dependency Injection, DI)需求,支持 按名称(byName)和按类型(byType)两种注入方式,属于 Java 标准注解,不依赖于 Spring 框架。
它的设计初衷是让 Java 应用能够以统一的方式声明对外部资源(如 Bean、JNDI 资源、数据源、EJB、Web 服务等)的依赖,而不依赖于具体的实现框架(如 Spring、EJB 容器等)。
@Resource
用法与@Autowired
用法
用法相似,也是做依赖注入的,从容器中自动获取bean。
@Resource 注解有两个核心参数:
name:指定要注入的 Bean 名称(byName 方式)
1
2
private OrderRepository orderRepo;type:指定要注入的 Bean 类型(byType 方式)
1
2
private CommentService commentService;对于泛型 Bean,需指定具体的泛型参数化类型:
1
2
3
4
5
6
7
8
9
10
11
public class UserCommentService implements CommentService<UserComment> { ... }
public class ProductCommentService implements CommentService<ProductComment> { ... }
public class CommentConsumer {
// 指定具体实现类
private CommentService<UserComment> userCommentService;
}
注意:
- 当
type
和name
不能同时用于精确匹配,否则会优先按name
查找
1 | // 可能导致冲突 |
- 若容器中存在多个相同类型的 Bean,会抛出
NoUniqueBeanDefinitionException
。 - 此时应改用
@Qualifier
或name
参数明确指定 Bean 名称。 - 当不指定任何参数时,默认采用byName方式,且名称为字段名或方法参数名。若字段类型本身已唯一(如具体实现类),无需额外指定
type
@Resource
不支持required=false
,不能注入可选依赖。
所以说@Resource
是基于名称(byName
)注入
Bean,若名称不存在则尝试按类型注入。是J2EE的JSR-250规范的注解。
注入原理与优先级
优先按 name 匹配:如果 name 属性有值,则直接按 name 查找 Bean。
name 为空时,按字段名/方法名查找:如果 name 没有指定,则用字段名或 setter 方法名作为 Bean 名称查找。
name 匹配不到时,按 type 匹配:如果按 name 没找到,再按 type 匹配(但 type 匹配如果有多个同类型 Bean,会报错)。
都找不到则报错:@Resource 默认是必须注入的,找不到会抛出异常。
@Resource
注解的工作流程如下:
- 在启动spring的时候,首先要启动容器;
- 启动spring容器时,会默认寻找容器扫描范围内的可加载bean,然后查找哪些bean上的属性和方法上有@Resource注解;
- 找到
@Resource
注解后,判断@Resource
注解括号中的 name 属性是否为空,如果为空:看spring容器中的bean的 id 与@Resource
要注解的那个变量属性名是否相同,如相同,匹配成功;如果不相同,看 spring 容器中 bean 的 id 对应的类型是否与@Resource
要注解的那个变量属性对应的类型是否相等,若相等,匹配成功,若不相等,匹配失败。 - 如果@Resource注解括号中的name属性不为空,看name的属性值和容器中的bean的id名是否相等,如相等,则匹配成功;如不相等,则匹配失败。
小知识:JSR 是 Java Specification Requests 的缩写,意思是“Java 规范提案”。任何人都可以提交 JSR 给 Java 官方,但只有最终确定的 JSR,才会以 JSR-XXX 的格式发布,如 JSR-250,而被发布的 JSR 就可以看作是 Java 语言的规范或标准。
@Resource
的三种使用场景
字段注入
1
2
3
4
5
6
7
8
public class UserService {
// 默认按字段名 "userRepository" 查找Bean
private UserRepository userRepository;
// 显式指定Bean名称
private OrderRepository orderRepo;
}Setter
注入1
2
3
4
5
6
7
8
9
public class LogService {
private LogRepository logRepository;
// 默认按方法参数名 "logRepository" 查找Bean
public void setLogRepository(LogRepository logRepository) {
this.logRepository = logRepository;
}
}构造方法注入(较少使用)
1
2
3
4
5
6
7
8
9
public class ProductService {
private final ProductRepository productRepository;
// 按参数名 "productRepository" 查找Bean
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
}
一般情况下,在同时使用 Spring 和 Java EE 标准的项目中,优先使用
@Resource
保持兼容性,避免与 @Autowired
混用,要注意由于 @Resource
不支持required=false
,对于可选依赖可使用
@Autowired
1 |
|
@Inject
@Inject 是 Java EE(现 Jakarta EE)标准中的依赖注入注解(JSR-330 规范),从 Java 6 开始引入。它是 Java 官方提供的依赖注入标准,旨在提供一种与具体框架无关的注入机制,使代码具有更好的可移植性。
所以,当项目需要同时兼容 Spring、CDI(Java
EE)等多个依赖注入框架时,项目中有跨框架的情况下,优先使用
@Inject
保持可移植性
基于类型的注入:@Inject
默认通过类型(byType)查找并注入依赖,与 Spring 的
@Autowired
类似。而且@Inject
默认要求依赖必须存在,相当于
@Autowired (required = true)
。若需要可选依赖,需配合其他机制(如
Optional)。
@Inject 本身只支持按类型注入,当存在多个同类型 Bean 时,需配合 @Named 注解(JSR-330 规范)指定名称:
使用 @Named 标记 Bean 名称
1
2
3
4
5
6
7
// 等同于Spring的@Service("alipayService")
public class AlipayServiceImpl implements PaymentService { ... }
public class WechatPayServiceImpl implements PaymentService { ... }然后使用 @Named 指定注入的 Bean
1
2
3
4
5
6
public class OrderService {
// 等同于@Autowired + @Qualifier("alipayService")
private PaymentService paymentService;
}
@Inject 的三种使用场景:
构造方法注入
在构造方法上使用 @Inject 时,其参数在运行时由配置好的IoC容器提供,规范中规定向构造方法注入的参数数量是0个或多个,所以在不含参数的构造方法上使用 @Inject 注解也是合法的。
1
2
3
4
5
6
7
8
9
public class UserService {
private final UserRepository userRepository;
// Spring 4.3+ 后可省略 @Inject
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}字段注入
1
2
3
4
5
public class OrderService {
private OrderRepository orderRepository;
}方法注入
1
2
3
4
5
6
7
8
9
public class LogService {
private LogRepository logRepository;
public void setLogRepository(LogRepository logRepository) {
this.logRepository = logRepository;
}
}
@ConfigurationProperties
那么他们之间的区别是什么
在Spring中依赖注入可以使用@Autowired、@Resource和@Inject来完成,并且在一般的使用中是可以相互替换的(注意是一般),不过三者还是有区别
@Autowired
注解:
是Spring本身替换的注解(
org.springframework.beans.factory.annotation.Autowired
),需要导入Spring相应的jar包才能使用可以标注的位置:构造器、方法、方法参数、变量域和注解上面
在Spring容器解析
@Autowired
注解时,使用的后置处理器为AutowiredAnnotationBeanPostProcessor
,在这个后置处理的注释中有这么一段:1
2
3
4
5
6
7
8{ org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}
* implementation that autowires annotated fields, setter methods, and arbitrary
* config methods. Such members to be injected are detected through annotations:
* by default, Spring's {@link Autowired @Autowired} and {@link Value @Value}
* annotations.
*
* <p>Also supports JSR-330's { javax.inject.Inject } annotation,
* if available, as a direct alternative to Spring's own {@code @Autowired}.大约意思就是,
AutowiredAnnotationBeanPostProcessor
是一个BeanPostProcessor
实现,其主要职责是:- 自动装配(注入)被注解标记的 字段(fields)、Setter 方法 和 任意配置方法。
- 这些需要被注入的成员(members)通过注解来识别,默认支持:
- Spring 原生的
@Autowired
和@Value
注解。 - JSR-330 标准的
@Inject
注解(如果项目中存在该依赖)。如果项目中引入了 JSR-330(Jakarta Inject) 的依赖(如javax.inject:javax.inject:1
),该处理器也会支持@Inject
注解,其功能与@Autowired
基本相同
- Spring 原生的
- 在 Bean 实例化后、初始化前,该处理器会扫描 Bean
的字段、方法,识别带有
@Autowired
、@Inject
或@Value
的成员。然后从 Spring 容器中查找匹配的 Bean 并完成注入。
@Autowired
注解有一个required
属性,当指定required
属性为false时,意味着在容器中找相应类型的bean,如果找不到则忽略,而不报错(这一条是两个注解所没有的功能)。默认优先按照类型去容器中找对应的组件,找到就赋值,如果找到多个相同类型的组件,再将属性的名称作为组件的 id 去容器中查找,如果组件 id 对象的bean不存在,而且
required
属性为true,就报错。支持@Primary注解,让Spring进行自动装配的时候,默认使用首选的bean
@Resource 注解
JSR250规范提供的注解(
javax.annotation.Resource
),不需要导入格外的包,这个注解在JDK的rt.jar
包中可以标注的位置:TYPE(表示可以标注在接口、类、枚举),FIELD(变量域)和METHOD(方法)上面。
在Spring容器解析
@Resource
注解时,使用的后置处理器为CommonAnnotationBeanPostProcessor
,在这个后置处理的注释中有这么一段:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18* { org.springframework.beans.factory.config.BeanPostProcessor} implementation
* that supports common Java annotations out of the box, in particular the JSR-250
* annotations in the {package. These common Java javax.annotation}
* annotations are supported in many Java EE 5 technologies (e.g. JSF 1.2),
* as well as in Java 6's JAX-WS.
*
* <p>This post-processor includes support for the {@link javax.annotation.PostConstruct}
* and {@link javax.annotation.PreDestroy} annotations - as init annotation
* and destroy annotation, respectively - through inheriting from
* {@link InitDestroyAnnotationBeanPostProcessor} with pre-configured annotation types.
*
* <p>The central element is the {@link javax.annotation.Resource} annotation
* for annotation-driven injection of named beans, by default from the containing
* Spring BeanFactory, with only {@code mappedName} references resolved in JNDI.
* The {@link #setAlwaysUseJndiLookup "alwaysUseJndiLookup" flag} enforces JNDI lookups
* equivalent to standard Java EE 5 resource injection for {@code name} references
* and default names as well. The target beans can be simple POJOs, with no special
* requirements other than the type having to match.大约意思就是
CommonAnnotationBeanPostProcessor
是一个BeanPostProcessor
实现,其主要职责是:- 支持 Java 标准注解(无需额外配置),特别是 JSR-250
规范中的
javax.annotation
包注解。 - 这些注解广泛应用于 Java EE 5 技术(如 JSF 1.2)和 Java 6 的 JAX-WS 中。
- 具体支持注解
@PostConstruct
:标记 Bean 初始化后执行的方法(等价于 Spring 的@PostConstruct
)。@PreDestroy
:标记 Bean 销毁前执行的方法(等价于 Spring 的@PreDestroy
)。
- 若同时使用
@Resource
和@Autowired
,Spring 会按以下顺序处理:@Resource
(由CommonAnnotationBeanPostProcessor
处理)@Autowired
(由AutowiredAnnotationBeanPostProcessor
处理)
CommonAnnotationBeanPostProcessor
是 Spring 框架中支持 Java 标准注解 的核心组件,它通过@Resource
实现按名称注入,并提供对@PostConstruct
和@PreDestroy
的支持,使 Spring 应用能够无缝集成 Java EE 标准注解,提高代码的可移植性和兼容性。- 支持 Java 标准注解(无需额外配置),特别是 JSR-250
规范中的
默认是按照组件名称进行装配的,
@Autowired
是根据类型,@Resource
是根据组件名称支持
@Primary
注解,不过首先按照会按照名称进行注入bean,先不执行@Primary
注解标注的优先的依赖注入,如果Spring IOC容器中没有该Bean,此时再按照@Primary
注解标注的bean进行装配
@Inject 注解
- JSR330规范提供的注解(
javax.inject.Inject
),主要导入javax.inject
包才能使用 - 可以标注的位置:方法、构造器和变量域中
- 在Spring容器解析
@Inject
注解时,使用的后置处理器和@Autowired
是一样的,都是AutowiredAnnotationBeanPostProcessor
。 - 由于
@Inject
注解没有属性,在加载所需bean失败时,会报错 - 除了上面的不同点之后,@Inject和@Autowired完全等价。
特性 | @Resource (JSR-250) | @Inject (JSR-330) | @Autowired (Spring) |
---|---|---|---|
所属规范 | Java 标准(Jakarta EE, JSR-250) | Java 标准(Jakarta EE, JSR-330) | Spring 框架原生注解 |
默认查找方式 | 按名称(byName),字段名或方法参数名 | 按类型(byType) | 按类型(byType) |
支持参数 | name, type, mappedName | - (配合 @Named 使用) | required, value(Spring 4.3+ 支持) |
多 Bean 处理 | 显式指定 name 或 type | 配合 @Named 或自定义限定符 | 配合 @Qualifier 或 @Primary |
依赖强制性 | 必须存在(无 required 参数) | 必须存在(无等效 required=false) | 支持 required=false(允许 null) |
可选依赖支持 | 不支持,需结合 @Autowired (required=false) | 需配合 Optional<>, Provider |
直接通过 required=false 支持 |
注入方式支持 | 字段、Setter 方法、构造方法(较少用) | 字段、Setter 方法、构造方法 | 字段、Setter 方法、构造方法、任意方法 |
优先级处理 | name 参数 > type 参数 > 字段名 | @Named 指定名称 > 类型匹配 | @Qualifier > @Primary > 类型匹配 |
容器查找顺序 | 1. 按 name 查找 2. 按 type 查找 | 1. 按类型查找 2. 按 @Named 名称查找 | 1. 按类型查找 2. 按 @Qualifier 名称查找 3. 按 @Primary |
与其他注解配合 | @PostConstruct, @PreDestroy | @Named, @Scope | @Qualifier, @Primary, @Lazy |
常见场景 | Java EE 兼容项目、JNDI 资源注入 | 跨框架项目、Java 标准依赖注入 | Spring 项目的首选注入方式 |
历史兼容性 | Java 6+ | Java 6+ | Spring 2.5+ |
框架集成性 | 支持 JSF、EJB 等 Java EE 技术 | 支持 CDI、Spring 等依赖注入框架 | 纯 Spring 生态系统 |
依赖包需求 | 无需额外依赖(Java EE 环境内置) | 需要 javax.inject 包(Java 9 + 为 jakarta.inject) | 内置在 Spring 框架中 |
循环依赖处理 | 与 @Autowired 类似,构造器注入可能触发循环依赖 | 与 @Autowired 类似,需通过 @Lazy 等方式解决 | 支持通过三级缓存解决部分循环依赖 |
JNDI 支持 | 原生支持,通过 mappedName 参数 | 不直接支持,需手动配置 | 不直接支持,需通过 JNDI 服务实现 |
标准化程度 | Java 官方标准,跨容器移植性高 | Java 官方标准,适合标准化开发 | Spring 特定实现,与框架深度耦合 |
错误处理机制 | 注入失败时抛出 NoSuchBeanDefinitionException | 注入失败时抛出异常,需手动处理 | 提供更详细的异常类型(如 NoUniqueBeanDefinitionException) |
最佳实践建议 | 1. 明确指定 name 参数 2. 处理 JNDI 资源 | 1. 配合 @Named 使用 2. 使用 Provider 处理可选依赖 | 1. 构造器注入优先 2. 配合 @Qualifier 处理多实现 |
总结:
核心差异解析
- 查找方式本质区别:
@Resource
以名称为核心,适合明确知道 Bean 名称的场景@Inject
和@Autowired
以类型为核心,适合面向接口编程
- 依赖强制性处理:
- Spring
的
@Autowired
提供更灵活的依赖控制,可通过required=false
实现可选依赖 - Java
标准注解需通过额外机制(如
Provider
)处理可选依赖
- Spring
的
- 多实现场景处理:
@Resource
通过name/type
参数直接指定@Inject
配合@Named
实现名称匹配@Autowired
通过@Qualifier
或@Primary
解决歧义
适用场景建议
- Java EE
兼容项目:优先使用
@Resource
和@Inject
,确保跨容器移植性 - 纯 Spring
项目:推荐使用
@Autowired
,充分利用 Spring 特性(如required
参数、@Primary) - 跨框架开发:使用
@Inject
+@Named
,保证代码在 Spring、CDI 等不同容器中的兼容性
高级特性对比
@Resource
的mappedName
参数提供 JNDI 资源注入能力,适合企业级 Java EE 环境@Inject
配合Provider
实现延迟依赖获取,是处理可选依赖的标准方式@Autowired
的@Primary
机制提供更简洁的默认实现选择方式
特性分类 | CommonAnnotationBeanPostProcessor | AutowiredAnnotationBeanPostProcessor |
---|---|---|
核心职责 | 处理 Java 标准注解(JSR-250),如 @Resource、生命周期注解 | 处理 Spring 原生注解及 JSR-330 注解,如 @Autowired、@Inject |
支持的注解 | @Resource, @PostConstruct, @PreDestroy, @Resource, @WebServiceRef | @Autowired, @Inject, @Value, @Lookup |
注入方式 | 按名称(byName)优先,字段名 / 参数名作为默认名称 | 按类型(byType)优先,类型匹配后通过 @Qualifier 细化名称 |
注入目标 | 字段、Setter 方法、构造方法(需显式标记) | 字段、Setter 方法、构造方法、任意方法(@Autowired 标记) |
JNDI 支持 | 原生支持,通过 mappedName 参数指定 JNDI 名称,支持 alwaysUseJndiLookup 配置 | 不直接支持 JNDI 注入,需通过 JndiTemplate 等工具类手动实现 |
生命周期注解处理 | 处理 @PostConstruct(初始化)和 @PreDestroy(销毁)注解 | 需通过 InitDestroyAnnotationBeanPostProcessor 单独处理 |
Java EE 兼容性 | 高(完全遵循 JSR-250 规范,支持 Java EE 容器如 GlassFish) | 低(Spring 专有注解,需框架适配才能在 Java EE 中使用) |
多 Bean 处理机制 | 注入时若存在多个同类型 Bean,必须通过 name/type 参数明确指定 | 优先通过 @Qualifier 指定名称,或通过 @Primary 标记默认实现 |
依赖强制性 | 注入失败时直接抛出异常,无 required 参数 | 支持 @Autowired (required=false) 实现可选依赖 |
处理阶段 | Bean 初始化阶段(postProcessAfterInitialization) | Bean 实例化后、初始化前(postProcessProperties) |
循环依赖处理 | 与 @Resource 配合时,构造器注入可能触发循环依赖问题 | 支持通过三级缓存解决部分循环依赖场景(字段注入 / Setter 注入) |
配置参数 | alwaysUseJndiLookup(强制 JNDI 查找)、jndiEnvironment 等 | required(依赖强制性)、annotationType(自定义注解类型) |
框架集成性 | 可与 JSF、EJB 等 Java EE 组件无缝集成 | 深度集成 Spring 生态,支持 AOP、事务等特性 |
依赖包需求 | 无需额外依赖(Java EE 环境内置 javax.annotation 包) | 内置在 Spring 框架中,JSR-330 支持需引入 javax.inject 包 |
注解优先级 | @Resource 的 name 参数 > type 参数 > 字段名 | @Qualifier > @Primary > 类型匹配 |
适用场景 | 1. Java EE 标准项目 2. 需要 JNDI 资源注入 3. 跨容器移植场景 | 1. 纯 Spring 项目 2. 面向接口编程 3. 复杂依赖关系管理 |
最佳实践 | 1. 明确指定 @Resource 的 name 参数 2. 配合 Java EE 规范使用 | 1. 构造器注入优先 2. 用 @Qualifier 处理多实现 3. @Value 注入配置 |
与其他处理器关系 | 可与 AutowiredAnnotationBeanPostProcessor 共存,处理不同注解 | 需要配合 CommonAnnotationBeanPostProcessor 实现完整功能 |
错误处理机制 | 注入失败时抛出 NoSuchBeanDefinitionException 等标准异常 | 提供更细化的异常类型(如 NoUniqueBeanDefinitionException) |
Spring Boot 自动配置 | Spring Boot 自动配置中默认启用,支持 @Resource 注解 | Spring Boot 默认启用,是依赖注入的核心处理器 |
职责与注解支持的本质区别
CommonAnnotationBeanPostProcessor
以Java 标准注解为核心,目标是兼容 Java EE 规范,适合需要跨容器移植的项目CommonAnnotationBeanPostProcessor
直接支持@PostConstruct
和@PreDestroy
,无需额外配置AutowiredAnnotationBeanPostProcessor
以Spring 特性为核心,提供更灵活的依赖注入控制,适合深度使用 Spring 框架的项目AutowiredAnnotationBeanPostProcessor
不直接处理生命周期注解,需配合InitDestroyAnnotationBeanPostProcessor
使用
注入逻辑的核心差异
graph TD
%% @Resource 注入流程
A[CommonAnnotationBeanPostProcessor] -->|注入流程| B[按name查找Bean]
B --> C{name存在?}
C -- 是 --> D[注入对应Bean]
C -- 否 --> E[按type查找Bean]
E --> F{唯一type?}
F -- 是 --> D
F -- 否 --> G[抛出异常]
%% @Autowired 注入流程
X[AutowiredAnnotationBeanPostProcessor] -->|注入流程| Y[按type查找Bean]
Y --> Z{唯一type?}
Z -- 是 --> D
Z -- 否 --> W[按Qualifier或Primary筛选]
W --> H{有唯一Bean?}
H -- 是 --> D[注入对应Bean]
H -- 否 --> G[抛出异常]
最后我们来看看这些注解的源码
@Autowired
1 | package org.springframework.beans.factory.annotation; |
@Resource
1 | // |
@Inject
1 | package jakarta.inject; // Java EE 8+ 及 Jakarta EE 版本包路径 |