面试回答喜欢用构造器注入,面试官很满意😎...

引言

大家在SpringBoot项目开发中进行依赖注入时,是不是都喜欢用字段注入呢?即使用@Autowired@Resource。没错,这种方式最简单与简洁,但是为什么在面试中,面试官问起你有关依赖注入的问题时,最好不要回答用字段注入呢?而是回答用构造器注入,接下来让我们一起来探讨一下常见的三种依赖注入方式。

字段注入(Field Injection)😵

字段注入(Field Injection)是Spring框架中依赖注入的一种方式,它允许开发者直接在类的字段上使用@Autowired或者@Resource注解来自动装配依赖。

下面通过一个简单例子来示例怎么使用字段注入:

java 复制代码
@Service
public class MyService {

    @Autowired
    private Dependency dependency;

    public void performAction() {
        dependency.doSomething();
    }
}

当这个类上面加了注解@Service,Spring就会将其当成一个Bean实例化到容器中方便取用,这样就可以避免多次创建或者销毁同一个类对象,方便复用,提高资源利用率。在这个例子中,MyService 类有一个 Dependency 类型的依赖,通过在字段上添加 @Autowired 注解,Spring 会自动在容器中寻找Bean,将合适的 Dependency Bean 注入到这个字段中。

@Autowired@Resource的区别

简单来说,@Autowired默认时通过类型匹配来进行依赖注入,而@Resource默认是通过基于名称来进行注入(是指bean在容器里面的名称🥹),所以你在使用@Resource时,最好清楚指定bean在容器中的名称哦。

  1. @Resource 只能用于字段或 setter 方法上,不能用在构造器上。
  2. 如果你没有指定 name 属性,Spring 会尝试使用字段名或 setter 方法的属性名作为 Bean 名称进行匹配。
  3. 当找不到名称匹配的 Bean 时,@Resource 不会回退到按类型匹配

设值方法注入 (Setter Injection)🤤

Setter注入通过类的setter方法来为类提供所需的依赖。这种方式与构造器注入相比,具有一定的灵活性,特别适合于那些依赖项可选或者希望在对象创建之后能够修改依赖的情况。

Tips: Setter注入通常遵循JavaBean规范,以set开头,后跟属性名,并且只有一个参数。

java 复制代码
@Service
public class MyService {

    private Dependency dependency;

    // Setter注入
    @Autowired
    public void setDependency(Dependency dependency) {
        this.dependency = dependency;
    }

    public void performAction() {
        dependency.doSomething();
    }
}

在这个例子中,MyService 类有一个 Dependency 类型的依赖,通过带有 @Autowired 注解的 setter 方法 setDependency 来注入这个依赖

  1. 灵活性:允许在对象创建之后更改依赖关系,这对于一些需要动态改变依赖的情况非常有用。
  2. 可选依赖 :如果某个依赖不是必须的,那么你可以不使用 @Autowired 注解,而是直接定义一个普通的 setter 方法,这样即使没有配置相应的 Bean,应用也不会出错

请注意: 即使Spring支持setter注入可以帮助解决某些类型的循环依赖问题,但应尽量避免设计上出现循环依赖的情况😵

构造器注入 (Constructor Injection)🤩

构造器注入 是 Spring 中最推荐的依赖注入方式之一。它通过类的构造函数(构造器)来注入依赖对象。Spring 容器在创建 Bean 实例时,会自动调用合适的构造器,并将所需的依赖作为参数传入。

java 复制代码
@Service
public class MyService {

    private final Dependency dependency;

    // 构造器注入
    public MyService(Dependency dependency) {
        this.dependency = dependency;
    }

    public void performAction() {
        dependency.doSomething();
    }
}

MyService 类需要一个 Dependency 类型的依赖,使用构造器注入后,该依赖在对象初始化时就被设置好了,但请注意:从 Spring 4.3 及以上版本 开始,如果类只有一个构造器,可以省略 @Autowired 注解,Spring 会自动识别并使用该构造器注入依赖。

为什么说构造器注入是最推荐的一种依赖注入方式🤓

保证不可变性

使用构造器注入,可以将依赖项声明为final字段。这意味着一旦对象被创建后,它的依赖就不会再改变。这种不变性有助于确保对象在其生命周期内的状态一致性,从而减少潜在的错误。

java 复制代码
public class MyService {
    private final Dependency dependency;

    public MyService(Dependency dependency) {
        this.dependency = dependency;
    }
}

在这个例子中,dependency 字段是 final 的,意味着它在对象被创建之后不能被修改。这增强了代码的安全性和可维护性。这在实战中一般通过使用 final 关键字定义依赖,防止它们在对象创建之后被修改。

保证依赖完整性

所有必须的依赖都在构造器中声明,保证了类在使用前就具备所有必需的依赖。这样错误就可以在编译阶段就可以检测出来,防止应用在运行时出现错误,也就避免了因依赖未注入而导致的 NullPointerException 等运行时错误。

易于单元测试

由于依赖是通过构造器传入的,你可以在测试中轻松地传入模拟对象(mock),而不需要依赖 Spring 容器。

java 复制代码
@Test
void testMyService() {
    Dependency mockDependency = Mockito.mock(Dependency.class);
    MyService service = new MyService(mockDependency); // 手动注入
    // ...
}

明确API设计

构造器清楚地表明了一个类所依赖的对象,提高了代码的可读性和可维护性。(这对于团队协作是非常重要的,你也不想被其他好厚米暴打吧🤣)

总结❤️

虽然说构造器注入十分推荐使用,但还是要具体情况具体实践,因为构造器注入也有其不足之处,比如要可选依赖时,这种情况更适合使用 setter 注入。如果依赖过多,构造器参数列表会变得冗长,影响可读性等问题,也可以尝试用字段注入或者Builder模式优化。总之一句话,具体情况具体实践!

如果你看了这篇文章有收获可以点赞+关注+收藏🤩,这是对笔者更新的最大鼓励!如果你有更多方案或者文章中有错漏之处,请在评论区提出帮助笔者勘误,祝你拿到更好的offer!

相关推荐
恸流失5 小时前
DJango项目
后端·python·django
萌新小码农‍6 小时前
Spring框架学习day7--SpringWeb学习(概念与搭建配置)
学习·spring·状态模式
Mr Aokey7 小时前
Spring MVC参数绑定终极手册:单&多参/对象/集合/JSON/文件上传精讲
java·后端·spring
地藏Kelvin8 小时前
Spring Ai 从Demo到搭建套壳项目(二)实现deepseek+MCP client让高德生成昆明游玩4天攻略
人工智能·spring boot·后端
菠萝018 小时前
共识算法Raft系列(1)——什么是Raft?
c++·后端·算法·区块链·共识算法
长勺8 小时前
Spring中@Primary注解的作用与使用
java·后端·spring
小奏技术9 小时前
基于 Spring AI 和 MCP:用自然语言查询 RocketMQ 消息
后端·aigc·mcp
编程轨迹9 小时前
面试官:如何在 Java 中读取和解析 JSON 文件
后端
lanfufu9 小时前
记一次诡异的线上异常赋值排查:代码没错,结果不对
java·jvm·后端
编程轨迹10 小时前
如何在 Java 中实现 PDF 与 TIFF 格式互转
后端