基于@Autowired依赖注入的原理分析

 更新时间:2025年06月29日 14:07:52   作者:找不到、了  
这篇文章主要介绍了基于@Autowired依赖注入的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

@Autowired 是 Spring 框架中的一个注解,用于自动注入依赖。

在 Spring 中,依赖注入(Dependency Injection, DI)是一种设计模式,允许在运行时将对象的依赖关系(即所需的其他对象)自动提供给它,而不是在代码中手动创建依赖对象。

1、介绍

以下为注解的结构图

该注解支持标注在字段、构造函数、方法以及参数上。

注意:

其中的关键属性 required 默认值为 true,表示如果没有合适的 Bean 可以注入,则会抛出异常。required 如果为false的时候,表示可以暂时不实例化。

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

2、实现原理

1、扫描及注册 Bean

Spring 在启动时会扫描配置的包,找到被@Compoent、@Service、@Repository和@Controller等注解标记的类,并将它们注册为 Spring 容器中的 Beans。

2、解析依赖

当 Spring 创建一个 Bean 时,它会检查该 Bean 的构造函数、方法或字段中是否有@Autowired注解。

这个注解表明该字段、构造函数或方法是需要进行依赖注入的。

3、类型匹配

Spring 会根据变量的类型去容器中查找匹配的 Bean,默认情况下,Spring 使用的是按类型自动装配。

  • 如果找到唯一的匹配项,就会将其注入。
  • 如果有多个匹配项,Spring 会抛出异常;可以通过设置required=false或者使用 @Qualifier或者@Primary来解决歧义问题。
  • 如果没有匹配项,通常会返回 null(前提是字段是可空的)。

3、使用场景

3.1、背景

当 Spring 容器检测到有多个同类型的 Bean 可供注入时,默认的行为是抛出 NoUniqueBeanDefinitionException 异常。

3.2、处理方式

1、@Qualifier

如果有多个相同类型的 Bean 时,可以使用 @Qualifier 注解来明确指定要注入的 Bean。

代码示例:

@Autowired
@Qualifier("specificBeanName")
private MyService myService;

2、@Primary注解

1、目的

主要目的是在 Spring 容器中有多个相同类型的 Bean 存在时,提供一种机制来指定哪个 Bean 应该被优先考虑作为默认注入的目标。

2、原理

如果其中一个 Bean 被标记为 @Primary,那么 Spring 将会选择它作为首选项并完成注入过程。

此逻辑发生在 Spring 的自动装配阶段,在这一阶段,容器会评估所有可用的候选 Bean,并根据各种规则(如 @Primary@Qualifier 等)做出最终决策

3、示例

@Configuration
public class AppConfig {

    @Bean
    @Primary
    public MyService primaryMyService() {
        return new MyServiceImpl1();
    }

    @Bean
    public MyService secondaryMyService() {
        return new MyServiceImpl2();
    }
}

在这个配置文件中,我们有两个实现了 MyService接口的服务类——MyServiceImpl1 和 MyServiceImpl2。由于我们在第一个服务实现上加了 @Primary 注解,因此无论何时需要注入 MyService类型的对象,都会优先选取 MyServiceImpl1 实例。

3.3、替代方式

1. @Inject

@Inject 是 Java EE 提供的标准注解,也可以在 Spring 中使用。

它的功能类似于@Autowired,但语义更加清晰,因为它仅关注依赖注入本身而不涉及 Spring 特定的功能。

public class ExampleService {
    private final AnotherService anotherService;

    @Inject
    public ExampleService(AnotherService anotherService) {
        this.anotherService = anotherService;
    }
}

2. 构造函数注入

这种方式被认为是最佳实践之一,尤其适用于强制性依赖项。相比于字段注入或 setter 方法注入,构造函数注入能更好地满足不可变性和测试需求。

示例:

public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) { // 构造函数注入
        this.userRepository = userRepository;
    }
}

3. @Resource

@Resource 是 JNDI 规范的一部分,通常基于名称匹配来查找目标 Bean。

如果没有找到与名字完全一致的 Bean,则会退回到按类型匹配的方式。相比 @Autowired 更加灵活,因为可以直接指定要注入的具体资源名。

示例:

public class MovieRecommender {
    @Resource(name="mainDataSource") // 明确指定了数据源的名字
    DataSource dataSource;
    
    public void recommend() {}
}

4、总结

通俗讲解

把@Autowired看成是一种“智能化的手”。当你需要一个助手(依赖对象)来完成某个任务时,你不需要去亲自找寻和雇佣这个助手,Spring 就像一个高效的秘书,知道你需要什么助手,会自动给你安排好。

你只需要告诉 Spring 你需要的助手的类型,它就会负责寻找并提供给你,而不需要你关心具体的细节。

这样做的好处是可以降低代码的耦合度,让程序的各个部分更容易进行单元测试和维护。只要我们在代码中声明需要的依赖,Spring 就会负责去处理这些依赖,让开发者能更专注于业务逻辑的实现。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • spring AOP注解失效原因分析及解决过程

    spring AOP注解失效原因分析及解决过程

    Spring AOP注解失效原因及解决方法,详细解析Spring动态代理机制,包括JDK动态代理和CGLIB动态代理,以及AOP注解在方法调用中的应用问题和解决方案
    2026-06-06
  • Java超详细梳理IO流的使用方法上

    Java超详细梳理IO流的使用方法上

    流(Stream)是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道,数据源发送的数据经过这个通道到达目的地,按流向区分为输入流和输出流
    2022-04-04
  • SpringBoot中的数据脱敏处理详解

    SpringBoot中的数据脱敏处理详解

    本文介绍了在SpringBoot中进行数据脱敏处理的方法,通过自定义注解和Jackson配置,可以轻松实现对敏感数据的脱敏,保护用户隐私
    2025-03-03
  • Mybatis基于xml配置实现单表的增删改查功能

    Mybatis基于xml配置实现单表的增删改查功能

    这篇文章主要介绍了Mybatis基于xml配置实现单表的增删改查,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • SpringBoot自动配置的8个技巧分享

    SpringBoot自动配置的8个技巧分享

    在 SpringBoot 2.x中,一个很核心的功能是自动配置机制,这篇文章主要为大家详细介绍了Spring Boot 2.x 实现自动配置的8个技巧,希望对大家有所帮助
    2025-01-01
  • SpringSecurity的防Csrf攻击实现代码解析

    SpringSecurity的防Csrf攻击实现代码解析

    这篇文章主要介绍了SpringSecurity的防Csrf攻击实现代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java集合框架数据存储与操作的神器

    Java集合框架数据存储与操作的神器

    Java集合框架提供了多种数据结构和操作方法,包括Collection接口、Map接口以及各种实现类,本文详细介绍了集合框架的层次结构、常见接口和实现类的特点、使用场景以及最佳实践,帮助开发者高效地进行数据存储和操作,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • Java 超详细讲解hashCode方法

    Java 超详细讲解hashCode方法

    在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致
    2022-04-04
  • 详解OpenAPI开发如何动态的添加接口实现

    详解OpenAPI开发如何动态的添加接口实现

    这篇文章主要为大家介绍了OpenAPI开发如何动态的添加接口实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • SpringBoot整合阿里 Druid 数据源的实例详解

    SpringBoot整合阿里 Druid 数据源的实例详解

    这篇文章主要介绍了SpringBoot整合阿里 Druid 数据源,主要讲解了手动配置方法,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11

最新评论