前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么不建议使用 @Autowired 字段注入却还可以使用 @Resource

为什么不建议使用 @Autowired 字段注入却还可以使用 @Resource

原创
作者头像
Lorin 洛林
发布2023-11-10 22:03:26
6670
发布2023-11-10 22:03:26
举报
文章被收录于专栏:Java 技术小屋

前言

  • hello,大家好,我是 Lorin,大家使用 Spring 框架 @Autowired 注解字段注入时是不是经常遇到这个问题,今天我们来看看为什么?
代码语言:txt
复制
Field injection is not recommended

版本

  • JDK 8
  • spring-boot-starter-parent 2.5.4

回顾一下 Spring 注入的三种方式

字段注入

代码语言:Java
复制
public class TestService {

    @Autowired
    private DependencyA dependencyA;

    @Autowired
    private DependencyB dependencyB;
}

方法注入

代码语言:Java
复制
public class TestService {

    private DependencyA dependencyA;

    private DependencyB dependencyB;

    @Autowired
    public void setDependencyA(DependencyA dependencyA) {
        this.dependencyA = dependencyA;
    }

    @Autowired
    public void setDependencyB(DependencyB dependencyB) {
        this.dependencyB = dependencyB;
    }
}

构造器注入

代码语言:Java
复制
public class TestService {

    private final DependencyA dependencyA;

    private final DependencyB dependencyB;

    // @Autowired 可以省略
    @Autowired
    public TestService(DependencyA dependencyA, DependencyB dependencyB) {
        this.dependencyA = dependencyA;
        this.dependencyB = dependencyB;
    }
}

为什么不推荐 @Autowired 字段注入

  • 从上面我们可以看到字段注入是最简单且无其它额外代码的方式,但同时也存在以下问题:

与特定 IOC 框架强耦合(最主要原因)

  • 与特定 IOC 框架强耦合,导致使用其它 IOC 容器框架时很难兼容。同时也导致单元测试必须使用特定框架实现组件管理,不容易进行单元测试。

无法实现像构造器注入不可变对象

使用字段注入的依赖对外部不可见

容易使对象违反单一职责原则

  • 由于字段注入使用过于简单,容易使对象过分膨胀,违反单一职责原则。

@Autowired VS @Resource

  • @Autowired 是Spring定义的,而 @Resource 是JSR-250定义。
  • 依赖识别方式:@Autowired默认是byType,可以使用@Qualifier指定Name,@Resource默认使用ByName,如果找不到则使用ByType。
  • 适用对象:@Autowired可以对构造器、方法、字段使用,@Resource只能对方法、字段使用。

@Resource 为什么没有不推荐

  • 其实这是因为 @Autowired 是 Spring 提供的特定注解,和 Spring 框架绑定,而 @Resource 是JSR-250提供的,它是Java标准,作为 IOC 容器框架都是需要实现的,所以不存在上面的第一点问题。

一些最佳实践

  • Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.
  • 翻译: 我们可以使用混合使用构造器注入和方法注入,一个好的经验法则是对于强制依赖使用构造器注入,而非强制依赖使用方法注入。在方法注入上使用 @Required 将依赖标志为非必填。
代码语言:Java
复制
public class TestService {

    /**
     * 必须依赖
     */
    private final DependencyA dependencyA;

    /**
     * 非必须依赖
     */
    private DependencyB dependencyB;

    public TestService(DependencyA dependencyA) {
        this.dependencyA = dependencyA;
    }

    @Autowired(required = false)
    public void setDependencyB(DependencyB dependencyB) {
        this.dependencyB = dependencyB;
    }

使用构造器注入带来的循环依赖问题

  • 如果我们使用构造器注入,那么可能会出现无法解析循环依赖的问题。这里提供两个解决方案:

使用方法注入(官网推荐)

  • One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

使用 Lazy 注解(推荐但谨慎使用)

  • 一些场景下会导致初次请求处理变慢。
代码语言:Java
复制
@Service
public class DependencyA {

    private final TestService testService;

    public DependencyA(@Lazy TestService testService) {
        this.testService = testService;
    }
}

@Service
public class TestService {

    private final DependencyA dependencyA;

    public TestService(DependencyA dependencyA) {
        this.dependencyA = dependencyA;
    }
}

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 版本
  • 回顾一下 Spring 注入的三种方式
    • 字段注入
      • 方法注入
        • 构造器注入
        • 为什么不推荐 @Autowired 字段注入
          • 与特定 IOC 框架强耦合(最主要原因)
            • 无法实现像构造器注入不可变对象
              • 使用字段注入的依赖对外部不可见
                • 容易使对象违反单一职责原则
                • @Autowired VS @Resource
                • @Resource 为什么没有不推荐
                • 一些最佳实践
                • 使用构造器注入带来的循环依赖问题
                  • 使用方法注入(官网推荐)
                    • 使用 Lazy 注解(推荐但谨慎使用)
                    • 个人简介
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档