千家信息网

Spring和IDEA为什么都不推荐使用@Autowired注解

发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,今天小编给大家分享一下Spring和IDEA为什么都不推荐使用@Autowired注解的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读
千家信息网最后更新 2024年11月20日Spring和IDEA为什么都不推荐使用@Autowired注解

今天小编给大家分享一下Spring和IDEA为什么都不推荐使用@Autowired注解的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    Spring为什么不推荐使用@Autowired 注解

    背景

    做开发的同学可能都会发现, idea 在我们经常使用的@Autowired 注解上添加了警告
    警告内容是: Field injection is not recommended, 译为: 不推荐使用属性注入

    我们点击右侧三个小点查看描述, 可以看到信息如下图

    原因详情描述: Inspection info: Spring Team recommends: "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies".
    译为: Spring 团队建议: 始终在您的 bean 中使用基于构造函数的依赖注入。始终对强制依赖项使用断言

    原因

    为什么 Spring 建议我们在Bean中使用构造注入呢?
    想要回答这个问题, 我们需要了解 Spring的依赖注入(DI)方式
    Spring常用的注入方式有: 简单类型注入, 集合类型注入, 域属性自动注入, 自动注入的类别, 空值注入, 构造注入
    可以简化为: 属性注入, 构造方法注入, set 方法注入

    下面, 来用代码展示下三种方式注入

    属性注入
    可以看到, 我们开发最常用的就是属性注入

    @RestControllerpublic class AppointmentNumberConfigurationController {    @Autowired    private AppointmentNumberConfigurationService numberConfigurationService;}

    set 方法注入
    set 方法注入也会用到@Autowired注解,但使用方式与属性注入有所不同,
    属性注入是用在成员变量上,而set 方法的时候,是用在成员变量的Setter函数上。

    @RestControllerpublic class AppointmentNumberConfigurationController {    private AppointmentNumberConfigurationService numberConfigurationService;    @Autowired    public void setNumberConfigurationService(AppointmentNumberConfigurationService numberConfigurationService) {        this.numberConfigurationService = numberConfigurationService;}

    构造方法注入
    Constructor Injection是构造器注入,是我们最为推荐的一种使用方式。
    但是, 每次注入都按照这样的流程去构造注入的话, 会显得比较麻烦.
    至于如何去简化这一步骤, 我们可以继续往下看.

    @RestControllerpublic class AppointmentNumberConfigurationController {    final AppointmentNumberConfigurationService numberConfigurationService;        public AppointmentNumberConfigurationController(AppointmentNumberConfigurationService numberConfigurationService) {        this.numberConfigurationService = numberConfigurationService;    }    }

    三种方式对比如下

    使用属性注入可能会出现的问题

    基于属性注入的方式, 违背单一职责原则
    因为现在的业务一般都会使用很多依赖, 但拥有太多的依赖通常意味着承担更多的责任,而这显然违背了单一职责原则.
    并且类和依赖容器强耦合,不能在容器外使用。
    基于属性注入的方式, 容易导致Spring 初始化失败
    因为现在在Spring特别是Spring Boot使用中, 经常会因为初始化的时候, 由于属性在被注入前就引用而导致npe(空指针错误),
    进而导致容器初始化失败(类似下面代码块). Java 在初始化一个类时,
    是按照 静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> @Autowired 的顺序。
    所以在执行这个类的构造方法时,person 对象尚未被注入,它的值还是 null。
    通过@Autowired 注入, 又因为是 ByType 注入, 因此有可能会出现两个相同的类型bean
    如下代码快, 就会产生两个相同的Bean, 进而导致Spring 装配失败
    //2. 基于属性注入的方式, 容易导致Spring 初始化失败@Autowiredprivate Person person;private String company;public UserServiceImpl(){    this.company = person.getCompany();}//3. 通过@Autowired 注入, 又因为是 ByType 注入, 因此有可能会出现两个相同的类型beanpublic interface IUser {    void say();}@Servicepublic class User1 implements IUser{    @Override    public void say() {    }}@Servicepublic class User2 implements IUser{    @Override    public void say() {    }}@Servicepublic class UserService {    @Autowired    private IUser user;}

    解决

    如果一定要使用属性注入, 可以使用 @Resource 代替 @Autowired 注解
    @Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
    如果我们想使用按照名称byName来装配,可以结合@Qualifier注解一起使用。

    如果可能的话, 尽量使用构造注入
    Lombok提供了一个注解@RequiredArgsConstructor, 可以方便我们快速进行构造注入, 例如:

    @RestController@RequiredArgsConstructorpublic class AppointmentNumberConfigurationController {        final AppointmentNumberConfigurationService numberConfigurationService;    }

    同时需要注意:

    使用@RequiredArgsConstructor注解需要导入Lombok 包 或者安装lombok 插件

            org.projectlombok      lombok      1.18.16  

    必须声明的变量为final

    根据构造器注入的,相当于当容器调用带有一组参数的类构造函数时,基于构造函数的 DI 就完成了,
    其中每个参数代表一个对其他类的依赖。基于构造方法为属性赋值,容器通过调用类的构造方法将其进行依赖注入

    思考

    为什么推荐使用@Resource,不推荐使用@Autowired

    通过对问题1 的梳理, 我们可以知道.
    因为@Autowired 注解在Bean 注入的时候是基于ByType, 因此会由于注入两个相同类型的Bean导致装配失败

    @Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
    如果我们想使用按照名称byName来装配,可以结合@Qualifier注解一起使用。

    @Resource装配顺序:
    ①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
    ②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
    ③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
    ④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

    因此, 如果一定要使用属性注入, 可以使用 @Resource 代替 @Autowired 注解

    @Autowired, @Qualifier, @Resource, 三者有何区别

    • @Autowired: 通过byType 方式进行装配, 找不到或是找到多个,都会抛出异常。

    • @Qualifier: 如果想让@Autowired 注入的Bean进行 byName装配, 可以使用 @Qualifier 进行指定

    • @Resource :作用相当于@Autowired,只不过 @Resource 默认按照byName方式装配, 如果没有匹配, 则退回到 byType 方式进行装配

    以上就是"Spring和IDEA为什么都不推荐使用@Autowired注解"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

    属性 装配 方式 注解 方法 推荐 类型 变量 容器 相同 两个 函数 知识 篇文章 上下 上下文 代码 作用 内容 只不过 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全教育视频2020 蚌埠app软件开发定制公司 栖霞区一站式软件开发排名靠前 怎样用电脑学习网络安全 网络安全防护面罩 中国网络安全是否就业前景好 国际版服务器试玩 易语言之内部数据库 基因型和基因表达量关联数据库 中职的网络安全与理科有关吗 国家电网二型网络安全监控 成都承办 届网络安全宣传周 南京天成网络技术有限公司 战争前线哪个服务器 网络安全与信息化重要性 数据库迁移到数据盘 网络安全利好国产软件吗 为什么网络中无法看到服务器 专科计算机网络技术专业工资 服务器怎样查跟踪路径 数据库知识点整理MySQL 大连的网络技术发展 网络安全知识素材视频 中国上市公司股票数据库 山东人工智能软件开发公司 网络安全集成龙头股 网络爬虫scrapy存入数据库 wps表格变成一行数据库 上海德颐网络技术服务中心 自动售货机数据库
    0