基于@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 就会负责去处理这些依赖,让开发者能更专注于业务逻辑的实现。

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

相关文章

  • SpringBoot Maven Clean报错解决方案

    SpringBoot Maven Clean报错解决方案

    这篇文章主要介绍了SpringBoot Maven Clean报错解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • 深入理解java中的拷贝机制

    深入理解java中的拷贝机制

    这篇文章主要给大家深入介绍了java中的拷贝机制,网上关于java中拷贝的文章也很多,但觉得有必要再深的介绍下java的拷贝机制,有需要的朋友可以参考学习,下面来一起看看吧。
    2017-02-02
  • Springboot详解如何整合使用Thymeleaf

    Springboot详解如何整合使用Thymeleaf

    这篇文章主要分享了Spring Boot整合使用Thymeleaf,Thymeleaf是新一代的Java模板引擎,类似于Velocity、FreeMarker等传统引擎,关于其更多相关内容,需要的小伙伴可以参考一下
    2022-06-06
  • SpringSecurity解决POST方式下CSRF问题

    SpringSecurity解决POST方式下CSRF问题

    本文主要介绍了SpringSecurity解决POST方式下CSRF问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 基于Java实现抽奖系统

    基于Java实现抽奖系统

    这篇文章主要为大家详细介绍了基于Java实现抽奖系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Spring框架原理之实例化bean和@Autowired实现原理方式

    Spring框架原理之实例化bean和@Autowired实现原理方式

    这篇文章主要介绍了Spring框架原理之实例化bean和@Autowired实现原理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • Java Swing实现JTable检测单元格数据变更事件的方法示例

    Java Swing实现JTable检测单元格数据变更事件的方法示例

    这篇文章主要介绍了Java Swing实现JTable检测单元格数据变更事件的方法,结合完整实例形式分析了Swing实现JTable检测单元格数据变更事件过程中出现的问题与相关解决方法,需要的朋友可以参考下
    2017-11-11
  • java利用Tabula实现对PDF内表格数据提取

    java利用Tabula实现对PDF内表格数据提取

    Tabula是一个开源工具,用于从PDF文档中提取表格数据,下面小编就来和大家详细介绍一下java如何通过Tabula对PDF文件内表格进行数据提取吧
    2023-09-09
  • Java利用反射获取object的属性和值代码示例

    Java利用反射获取object的属性和值代码示例

    这篇文章主要介绍了Java利用反射获取object的属性和值代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 关于分布式锁(Redisson)的原理分析

    关于分布式锁(Redisson)的原理分析

    这篇文章主要介绍了关于分布式锁(Redisson)的原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论