🤔同事问我Spring中的注解@Autowired是啥意思?我...

250 阅读8分钟

🏆本文收录于「滚雪球学SpringBoot」(全网一个名)专栏,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

✨ 前言

  哈咯啊,jy萌!我又来了。今天我们来聊点啥呢?欢迎评论区讨论,呼声最高者下期安排。如果你使用Spring框架已有几年,或者刚刚开始接触Spring架构,那你你一定在项目中见过或听说过@Autowired这个注解吧,没错,本期我就给大家好好唠唠它。我作为一个资深码农,基本项目中都频繁地用它,这个注解带来了很多便利,但如果我采访你们,不知能够回答出来几点?首先,它可以帮助我们进行依赖注入,减少了代码中的耦合,提升代码可维护性。那么,@Autowired,它究竟是做什么的呢?为什么它这么重要?本地,我就带大家一起来深入剖析下这个注解,解答如上常见疑问。

  结合我多年的开发经验,@Autowired,它是Spring中最常用的注解之一你说没用过或者没见过,我会怀疑你不是Java开发,为什么?因为它不仅简化了依赖注入的过程,还让我们能够灵活地管理对象之间的依赖关系,如果你一个都不用,那你倒是真牛批。接下来,让我们以实战开发的角度来聊聊,这个注解到底是怎么在我们的项目中发挥作用的。

🤔 什么是@Autowired?它是做什么的?

  正如标题所问,我来概括性总结下,@Autowired是Spring框架中的一个注解,用来实现依赖注入(DI,Dependency Injection)。它标注的字段、构造方法或方法的参数会自动由Spring容器提供对应的依赖对象。换句话说,@Autowired告诉Spring:“嘿,我需要这个对象,请帮我自动注入。”,通俗易懂吧,是不是一下就明白了。

依赖注入(DI)——让Spring管理对象

  在Spring框架中,依赖注入(DI)是实现控制反转(IoC,Inversion of Control)的核心方式,如果你连DI都不了解,那请去看我往期文章,先恶补下。通过依赖注入,Spring容器会负责对象的创建、生命周期管理以及它们之间的依赖关系。开发者只需要告诉Spring哪些对象需要被注入,Spring会自动提供适当的对象实例,并将它们注入到需要的地方,压根不需要人为去一一注入。

  @Autowired注解正是帮助我们实现这一功能的工具,它可以用来自动注入:

  • 字段(Field)
  • 构造方法(Constructor)
  • Setter方法

  这些方式都可以通过@Autowired来实现依赖注入,Spring会根据上下文自动决定应该注入哪个对象。

🌟 @Autowired 的三种常见用法

  身为一名身经百战的码农,我可以负责任的告诉你,@Autowired注解的使用非常灵活,它有几种常见的用法,可以帮助我们高效地注入依赖。接下来,我会会一一介绍一波:

1. 字段注入(Field Injection)

  常见用法之一,也是最简单和最常见的方式,直接在类的字段上使用@Autowired注解。这种方式不需要提供构造方法或setter方法,Spring会自动把对应的Bean注入到该字段中。举个例子:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void createUser(User user) {
        userRepository.save(user);
    }
}

  在这个例子中,@Autowired标记了userRepository字段,Spring容器会自动为我们注入一个UserRepository的实例。这是最直观的依赖注入方式,通常在Spring开发中非常常见。

  那么针对此种方法,是否是百分百适配所有场景的呢?非也...它既有优点也有缺点,如下:

优点:

  • 简单快捷,代码较为简洁。
  • 适用于大多数场景,开发效率较高。

缺点:

  • 由于没有明确的构造函数,导致代码不太容易进行单元测试。
  • 隐式的依赖关系,可能在复杂的应用中不易管理。

2. 构造方法注入(Constructor Injection)

  除了如上这种,那就当属构造方法注入了,它是Spring推荐的最佳实践。它通过构造方法来注入依赖,确保了对象的不可变性和更好的测试性。具体做法是将依赖对象作为构造方法的参数,然后使用@Autowired标注构造方法。Spring容器会自动通过构造方法注入对象。

@Service
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void createUser(User user) {
        userRepository.save(user);
    }
}

  在这个例子中,UserService类通过构造方法注入了UserRepository。这种方式确保了依赖的不可变性,并且让依赖关系变得更加清晰。

  那么针对此种方式注入,是否是百分百适配所有场景的呢?非也...它既有优点也有缺点,如下:

优点:

  • 通过构造方法注入,依赖关系更加显式,代码更加清晰。
  • 有助于单元测试,因为可以通过构造方法轻松提供依赖。
  • 可以确保依赖关系的不可变性。

缺点:

  • 相比字段注入,代码稍显繁琐。
  • 需要手动定义构造方法,尤其是在依赖较多时,可能需要更多的代码。

3. Setter方法注入(Setter Injection)

  最后一种,Setter方法注入,这种使用方式是通过类的setter方法来注入依赖。Spring会自动调用set方法,并传入相应的对象。这种方式适合在需要选择性注入依赖或者依赖是可选的情况下使用。

@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void createUser(User user) {
        userRepository.save(user);
    }
}

  在这个例子中,@Autowired标记了setUserRepository方法,Spring会自动调用这个setter方法来注入UserRepository

  那么针对此种方式注入,同样,它既有优点也有缺点,如下:

优点

  • 适合在依赖关系较复杂或需要条件注入的场景下使用。
  • 可以提供默认值,适合可选依赖的情况。

缺点

  • 代码不如构造方法注入清晰。
  • 不保证依赖关系的不可变性,可能导致在对象创建后依赖被修改。

🌟 @Autowired 的高级用法

  当然,除了如上几种最常见的使用方式之外,我们是否还有些“特殊”用法,答案肯定是有的。我在实际开发项目中,就有遇到一些更复杂的依赖注入场景,用到了@Autowired的一些高级用法,具体如下:

1. 自动注入多个候选Bean时的解决方案

  在某些场景下,Spring容器中可能会有多个相同类型的Bean,@Autowired就会遇到注入冲突。Spring会抛出NoUniqueBeanDefinitionException异常,因为它无法确定到底应该注入哪个Bean。

  解决这个问题的办法是使用@Qualifier注解来指定具体的Bean:

@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;

  通过@Qualifier注解,Spring就能知道该注入哪个具体的Bean,避免了冲突。

2. @Autowired@Primary的结合

  如果你有多个候选Bean,但希望某个Bean优先被注入,可以使用@Primary注解标记一个Bean为首选Bean。然后,@Autowired注解会优先注入这个@Primary标记的Bean。

@Bean
@Primary
public UserRepository primaryUserRepository() {
    return new UserRepositoryImpl();
}

  这样,Spring会优先注入primaryUserRepository,即使容器中有多个UserRepository的实现类。

  当然,面对如上场景,除了这么干肯定也还有其他实现方式,但是我习惯结合@Autowired来使用,这点大家不要被我带偏了。

🧩 总结

  讲到这里,我想说,通过我多年的开发经验,@Autowired注解,绝壁是Spring框架中依赖注入机制的核心,它大大简化代码中的对象管理和依赖关系,让我们更专注于业务逻辑的实现而不需要考虑Bean之间的关系。无论是字段注入、构造方法注入,还是Setter方法注入,@Autowired都能帮助我们轻松地实现自动化的依赖注入,从而减少了手动创建对象的繁琐,这点是毋庸置疑的。

  而且,@Autowired不仅能提高代码的简洁性和可维护性,还能帮助我们清晰地管理依赖关系,确保应用的解耦。而在实际项目开发中,合理地运用@Autowired注解,结合@Qualifier@Primary等注解,可以大大帮助我们更高效地解决复杂的依赖问题。

💬 你怎么看?

  最后,我相信你一定也有一些关于@Autowired的开发经验吧?你是如何解决注入冲突的?使用@Autowired时有没有遇到过其他有趣的玩法?欢迎在评论区与我分享你的经验,让我们一起探讨如何更好地运用@Autowired,写出更加优雅的Java语句!🚀

  OK,以上就是我本期的全部内容啦,感谢大家的阅读陪伴,咱们下期再见~~

📣 关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主&最具价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-