为什么IDEA提示不推荐@Autowired?如果使用@Resource呢?

因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享

点击关注#互联网架构师公众号,领取架构师全套资料 都在这里

0、2T架构师学习资料干货分

上一篇:2T架构师学习资料干货分享

大家好,我是互联网架构师!

来源:juejin.cn/post/7463352165487935542

前言

在使用 Spring 框架时,依赖注入(DI)是一个非常重要的概念。通过注解,我们可以方便地将类的实例注入到其他类中,提升开发效率。

@Autowired又是被大家最为熟知的方式,但很多开发者在使用 IntelliJ IDEA 时,常常看到 IDEA 提示不推荐使用@Autowired,这是为什么呢?

今天讲一下我对于@Autowired字段注入的理解。


1. 为什么不推荐使用@Autowired?

1.1. 隐式依赖

@Autowired会根据类型自动注入依赖,可能导致依赖不明确。特别是在存在多个符合类型的候选对象时,可能会导致注入失败或错误地注入实例。

1.2. 循环依赖

@Autowired可能导致循环依赖,尤其在单例 Bean 中,虽然 Spring 有解决方案,但仍需额外处理。

1.3. 生命周期不透明

通过@Autowired注入的 Bean 由 Spring 管理,类无法显式了解其生命周期。相比之下,构造器注入可以显式管理依赖的生命周期。

1.4. 不符合不可变性原则

字段注入使得依赖关系在对象生命周期内可能发生变化,而构造器注入确保依赖在对象创建时设定,符合不可变性原则。

经常看到的争议点:不推荐使用@Autowired,所以就使用@Resource(使用@Resource时,IDEA不会有波浪线提示)。


2. @Autowired和@Resource的基本用法

2.1. @Autowired

@Autowired是 Spring 提供的注解,用于自动注入依赖项。Spring 会根据类型(默认情况下)或者名称(通过 @Qualifier)来自动注入所需的 Bean。

@Autowired
private UserService userService;

在这个例子中,Spring 会自动将 UserService 类型的 Bean 注入到 userService 属性中。

2.2. @Resource

@Resource 是 Java 规范的一部分,来自 javax/jakarta.annotation 包,它更注重按照名称来注入 Bean。默认情况下,它会尝试按名称匹配,但如果没有找到匹配的名称,再通过类型注入。

@Resource
private UserService userService;

@Autowired不同@Resource会首先查找名为userService的 Bean,如果找不到,再通过类型注入。

可以看出其实两者本质上是没有区别的,只是匹配顺序不一样。


3. @Autowired和@Resource实测对比

假如有一个接口类,如下:

@Service
publicinterfaceUserService{
    // 用户服务...
}

两个实现类,如下:

@Component
publicclassUserServiceImplimplementsUserService{
    // 实现细节
}

@Component
publicclassAnotherUserServiceImplimplementsUserService{
    // 另一个实现
}
3.1. 使用@Autowired做测试

在测试接口里面加入@Autowired,如下:

/**
 * 测试接口
 */
@RestController("test")
publicclassTestController{  
    @Autowired
    private UserService userService;
}

启动项目,控制台输出错误,如下:

图片

错误提示:需要一个bean,但是找到了两个bean。

修改之后指定具体的bean名,如下:

@RestController("test")
publicclassTestController{  
    @Autowired
    // @Qualifier("userServiceImpl")  // 或者使用Qualifier来指定bean名
    private UserService userServiceImpl;
}

启动项目,项目正常启动,断点测试如下:

图片 图片

正常获取到需要的bean实例。

3.2. 使用@Resource做测试

在测试接口里面加入@Resource,如下:

/**
 * 测试接口
 */
@RestController("test")
publicclassTestController{
    @Resource
    private UserService userService;
}

启动项目,控制台输出错误,如下:

图片

错误提示:需要一个bean,但是找到了两个bean。

修改之后指定具体的bean名,如下:

@RestController("test")
publicclassTestController{  
    @Resource
     // @Resource(name = "userServiceImpl")  // 或者使用name来指定bean名
    private UserService userServiceImpl;
}

启动项目,项目正常启动,断点测试如下:

图片 图片

正常获取到需要的bean实例。

可以看出实际上@Autowired@Resource的使用效果是一样的。(@Resource并不优于@Autowired,两者都是基于字段注入。甚至于在Spring框架中,@Autowired性能更好,例如:自动装配的细粒度控制 。)


4. 推荐注入的方式

构造器注入是推荐的首选方式,尤其在处理复杂依赖关系、不可变对象、单元测试等场景时,构造器注入非常有用。

4.1. 推荐原因
  • 显式依赖关系: 构造器注入使依赖关系在对象创建时就显式地列出,代码更清晰。

  • 不可变性: 依赖可以声明为 final,避免修改。

  • 避免循环依赖: 能及时发现并避免循环依赖问题。

  • 明确依赖关系: 构造器清晰暴露依赖,增强代码可读性。

4.2. 示例
@RestController("test")
publicclassTestController{
    privatefinal UserService userService;

    publicTestController(UserService userServiceImpl){
        this.userService = userServiceImpl;
    }
}

// 或者使用lombok简化代码。
@RestController("test")
@RequiredArgsConstructor
publicclassTestController{
    privatefinal UserService userServiceImpl;
}

伪逻辑说明:

  • 显式依赖关系: 应该关注的是,整个项目的代码规范,而不是针对具体的某一个类去优化,使用构造器注入。

  • 不可变性: 应该关注的是,合理的设计,项目中bean在初始时,如果使用@Autowired注入某个类,就应该不在初始化期间去修改它。

  • 避免循环依赖: 也是和项目的架构相关,如果无法中设计上避免,也可以通过代理和懒加载去解决。

  • 明确依赖关系: 如果项目类名命名规范,不使用相同的类名,或者使用一些前缀后缀去区分,也能够不影响依赖关系。


5. 构造器一定优于@Autowired吗?

@Autowired在一些方面要优于构造器注入?

  • 简化代码: 自动注入依赖,无需手动编写构造器或 setter 方法,代码更简洁。

  • 快速开发: 灵活且快速,不需要修改构造函数,可以直接通过字段注入依赖。

  • 自动依赖管理: Spring 自动管理依赖,简化了依赖的选择和注入过程。

  • 避免构造函数冗长: 对于依赖较多的类,字段注入避免了构造函数过长的问题。


结语

虽然 IDEA 提示不推荐使用 @Autowired,但这并不意味着它是一个糟糕的选择。不同的注入方式有其各自的优缺点,选择依赖注入方式时,应该根据项目规模、复杂性以及团队编码习惯来决定,而不是盲目跟随趋势。

认说到底,程序从职场角度看,公司这样做很可能是想“信息差”捞点回本。建议保存所有当年的交接记录、邮件、IM聊天截图,必要时走仲裁流程,不然这种事开了先例,下一个就可能是别人员写代码要留注释,职场上做事也要留痕迹。只有手里握着证据,才能不被随便背锅。,

1、2T架构师学习资料干货分享

2、10000+TB 资源,阿里云盘,牛逼!!

3、基本涵盖了Spring所有核心知识点总结

  · END ·

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描上方二维码关注一下,您的支持是我坚持写作最大的动力。

求一键三连点赞、转发、在看

<think>我们正在解决IntelliJ IDEA@Autowired注解爆红的问题。根据引用内容,爆红的原因主要是IDEA对Spring的注入检查比较严格,而Mybatis的Mapper接口没有被正确识别为Spring Bean。虽然实际运行报错,但影响代码美观。以下是几种解决方案: 1. 在DAO层(Mapper接口)添加@Repository注解(引用[1])。这样明确告诉Spring这是一个Repository组件,IDEA就能识别了。 ```java @Repository public interface UserDao { // ... } ``` 2. 修改IDEA的检查级别(引用[3][4]):将Autowiring for Bean Class的严重级别从Error改为Warning,或者直接关闭检查。 - 步骤:File -> Settings -> Editor -> Inspections -> 搜索"Spring" -> 展开Spring Core -> Code -> 找到"Autowiring for Bean Class" -> 右侧Severity选择Warning(或取消勾选)-> Apply。 3. 使用@Resource注解替代@Autowired(引用[2]未直接提及,但常见做法)。因为@ResourceJava标准注解,依赖Spring,且IDEA对其检查可能更宽松。 ```java @Resource private UserDao userDao; ``` 4. 使用构造器注入(Spring推荐方式),这样仅符合Spring的最佳实践,而且能避免IDEA的警告(因为构造器注入是显式的,IDEA容易识别)。 ```java private final UserDao userDao; @Autowired public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } ``` 5. 确保Mapper接口被Spring扫描到。在Spring Boot中,通常需要在启动类上添加@MapperScan注解指定Mapper接口的包路径(引用[2]提到Mybatis的@Mapper注解,但需要确保扫描)。 ```java @SpringBootApplication @MapperScan("com.example.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 总结:推荐优先使用第1种(加@Repository)或第5种(确保扫描)从根源解决,或者使用第4种构造器注入(最佳实践)。如果只是临时消除警告,可以选择第2种修改IDEA设置。 相关问题: 1. 为什么IntelliJ IDEA@Autowired注入检查比Eclipse严格? 2. 使用@Autowired注解时,如何避免空指针异常? 3. Spring Boot中如何正确配置Mybatis的Mapper接口? </think>### IntelliJ IDEA@Autowired注解爆红问题的解决方案 根据引用内容分析,该问题本质是IDEA的严格代码检查机制与Mybatis框架的兼容性问题。以下是已验证的解决方案: #### ✅ 根治方案(推荐) 1. **DAO层添加注解** 在Mybatis的Mapper接口上添加`@Repository`注解(Spring标准注解),明确声明其为Spring组件: ```java @Repository // 添加此注解 public interface UserDao { // Mybatis Mapper方法 } ``` *原理*:IDEA需要明确识别Bean定义(引用[1]),此方案符合Spring规范且一劳永逸。 #### ⚠️ 临时缓解方案 2. **调整IDEA检查级别**(引用[3][4]) - `File > Settings > Editor > Inspections` - 搜索栏输入 `Spring` > 展开 `Spring Core > Code` - 找到 `Autowiring for Bean Class` - 将 `Severity` 从 `Error` 改为 `Warning` 或直接取消勾选 - 点击 `Apply` 生效 *注意*:此方法仅是隐藏警告,解决根本问题。 #### 🔧 进阶方案 3. **改用构造器注入**(Spring官方推荐) ```java @Service public class UserService { private final UserDao userDao; // 构造器注入替代@Autowired public UserService(UserDao userDao) { this.userDao = userDao; } } ``` *优势*:避免字段注入问题,且IDEA完全兼容。 4. **确保Mapper扫描正确** 在启动类添加`@MapperScan`注解明确扫描路径: ```java @SpringBootApplication @MapperScan("com.example.dao") // 指定Mybatis接口包路径 public class Application { ... } ``` #### ❌ 推荐的方案 - 修改Spring错误级别为Warning(引用[4]):掩盖潜在问题 - 移除项目Spring关联(引用[1]):导致其他功能异常 - 安装非官方插件:可能引入稳定因素 > **根本原因总结**(引用[2]):IDEA无法确认Mybatis的`@Mapper`接口生成的代理对象是否为非NULL,而`@Autowired`要求注入非空对象。通过`@Repository`或构造器注入可显式声明Bean身份。 --- ### 相关问题 1. 为什么Mybatis的Mapper接口需要用`@Repository`注解而用`@Component`? 2. Spring的构造器注入相比字段注入有哪些优势? 3. 如何在IntelliJ IDEA中自定义代码检查规则?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值