为什么在Spring中使用@Autowired时会报错 而@Resource不会

目录

Spring常见的依赖注入(DI)方式

属性注入(Field注入)的缺点

@Autowired VS @Resource

为什么IDEA只对@Autowired警告,却对@Resource视而不见呢?


Spring常见的依赖注入(DI)方式

  1. 构造函数注入(Constructor Injection)
    构造函数注入是在类的构造函数中声明 Bean 的依赖项,Spring 在创建 Bean 时通过构造函数来注入依赖项。构造函数注入是一种类型安全、清晰、可测试的依赖注入方式,由于必须在构造函数中传递所有依赖的依赖项,比较容易发现依赖项问题。
    public class ExampleService {
      private final ExampleRepository repository;
    
      public ExampleService(ExampleRepository repository) {
        this.repository = repository;
      }
      // More methods
    }
  2. 属性注入(Property Injection)
    属性注入是在类的属性上使用注解或配置文件来声明 Bean 的依赖项,Spring 在创建 Bean 后通过为属性设值的方式来注入依赖项。相对于构造函数注入,属性注入更加简便,但由于存在循环依赖等问题,容易带来一些意外的问题。
    public class ExampleController {
      @Autowired
      private ExampleService service;
      
      // More methods
    }
  3. 方法注入(Method Injection)
    方法注入是在类的方法上使用注解或者配置文件来声明 Bean 的依赖项,Spring 在创建 Bean 后通过调用Bean的方法来注入依赖项。方法注入的方式相对柔性,常用于一些具有特殊需求的 Bean 注入情况。
    public class ExampleService {
      private ExampleRepository repository;
    
      @Autowired
      public void setRepository(ExampleRepository repository) {
        this.repository = repository;
      }
      // More methods
    }

    其中,构造函数注入是被 Spring 官方所推荐的一种依赖注入方式,因为构造函数的依赖关系是非循环的并且类型安全的,能够有效地避免一些意外情况的发生。同时,属性注入、方法注入虽然也有它们独特的使用场景,但它们都不够优雅和安全,需要尽量避免使用。

属性注入(Field注入)的缺点

在 Spring 的依赖注入过程中,属性注入虽然比构造函数注入更加简单方便,但也存在一些缺点:

1.无法保证依赖项的完成性

使用属性注入方式时,由于容器在创建 Bean 后直接为属性赋值,无法保证依赖项已经被完全初始化。如果一个 Bean 的依赖项没有正确初始化,就会引发一系列意外的问题。而构造函数注入能够保证在构造函数中传递所有依赖的依赖项,从而更容易发现依赖项问题。

2.循环依赖能够发生

使用属性注入时,如果两个或多个 Bean 相互依赖,循环依赖可能发生。在这种情况下,Spring 会将其中一个 Bean 创建一个代理对象,并将另一个 Bean 注入到该代理对象中。这会带来额外的性能开销以及可能出现预期外的错误。

3.加载顺序由 Spring 确定,不够自由

使用属性注入时,我们不能保证在所有的属性已经设置之前是否已经调用了其他方法。这通常不是问题,但是在某些情况下,构造函数注入能够提供更高的可读性和可测试性。

4.依赖过多时不够明显

比如我需要10个依赖,用构造器注入就会显得庞大,这时候应该考虑一下此组件是不是违反了单一职责原则

5.不能像构造器那样注入不可变的对象

5.依赖对外部不可见

外界可以看到构造器和setter,但无法看到私有字段,自然无法了解所需依赖

综上,属性注入虽然更加方便,但是存在一些缺点。在开发中,应该根据具体需要选择合适的注入方式,避免导致依赖项问题和其他潜在的风险。同时,尽管属性注入被批评为“背刺式注入”,但它仍然可以在适当的场合下使用,并且是广泛使用的依赖注入方式之一。

@Autowired VS @Resource

事实上,他们的基本功能都是通过注解实现依赖注入 ,只不过@Autowired是Spring定义的,而@Resource是JSR-250定义的。大致功能基本相同,但是还有一些细节不同:

  • 依赖识别方式 :@Autowired默认是根据类型 (byType), 可以使用@Qualifier指定Name,@Resource默认时根据名字(ByName ),如果找不到再根据类型(ByType)
  • 适用对象 :@Autowired可以对构造器、方法、参数、字段 使用,@Resource只能对方法、字段使用
  • 提供方 :@Autowired是Spring 提供的,@Resource是JSR-250 提供的

为什么IDEA只对@Autowired警告,却对@Resource视而不见呢?

  1. @Autowired 是Spring 提供的,它是特定IoC提供的特定注解 ,这就导致了应用与框架的强绑定 ,一旦换用了其他的IoC框架,是不能够支持注入的。而 @Resource 是JSR-250 提供的,它是Java标准 ,我们使用的IoC容器应当去兼容它,这样即使更换容器,也可以正常工作。
  2. 同时,@Autowired和 @Resource的默认注入方式不同,@Autowired默认是根据类型进行注入的, @Resource默认是先根据名字注入,找不到再根据类型注入的。所以,相比于 @Autowired 注解,@Resource 注解更加灵活,但同时也更难以确保依赖项的正确性。如果无法确定自动注入的 Bean 是否正确,可以通过 @Qualifier 注解或者手动注入的方式显式指定 Bean 的名称或类型,避免依赖项注入的错误和困扰。

参考文章:为什么 Spring和IDEA 都不推荐使用 @Autowired 注解

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值