构造函数注入在spring boot 中怎么使用详解

发布于:2025-07-08 ⋅ 阅读:(14) ⋅ 点赞:(0)

我们来详细讲解一下在 Spring Boot 中如何使用构造函数注入,并通过一个完整的、可运行的例子来演示。

构造函数注入是 Spring 官方最推荐的依赖注入方式,因为它能保证对象的不可变性和依赖的完整性。

核心理念

在 Spring Boot 中使用构造函数注入非常简单,你只需要做到:

  1. 在你的类中,创建一个需要依赖作为参数的构造函数。
  2. 将依赖字段声明为 private final
  3. 就这样,完成了! Spring Boot 会自动检测到这个构造函数,并为你注入所需的 Bean。

一个关键点:自 Spring 4.3 版本以后,如果一个类只有一个构造函数,那么 Spring 会自动用它来进行依赖注入,你不再需要在构造函数上显式地添加 @Autowired 注解。这让代码变得更加干净。


举例说明:一个简单的通知服务

我们来创建一个场景:一个 NotificationController(通知控制器)需要依赖一个 MessageService(消息服务)来发送通知。

项目结构
src/main/java/com/example/demo/
├── controller/
│   └── NotificationController.java
├── service/
│   ├── MessageService.java       (接口)
│   └── EmailService.java         (实现)
└── DemoApplication.java          (主启动类)
第1步:创建依赖接口和实现

首先,我们定义消息服务的接口和它的一个具体实现(比如邮件服务)。

MessageService.java (接口)

package com.example.demo.service;

public interface MessageService {
    String sendMessage(String message);
}

EmailService.java (实现类)

这个类会被 Spring 作为一个 Bean 来管理。

package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service // 1. 标记为 @Service,让 Spring 扫描并创建一个 Bean
public class EmailService implements MessageService {

    @Override
    public String sendMessage(String message) {
        System.out.println("正在通过邮件发送消息: " + message);
        return "邮件发送成功: " + message;
    }
}
第2步:在控制器中使用构造函数注入

现在,我们在 NotificationController 中通过构造函数来注入 MessageService

NotificationController.java (消费者)

这是演示构造函数注入的核心代码。

package com.example.demo.controller;

import com.example.demo.service.MessageService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class NotificationController {

    // 2. 将依赖声明为 private final
    // final 确保了依赖在对象创建后不会被修改
    private final MessageService messageService;

    // 3. 定义一个构造函数,并将依赖作为参数传入
    // 因为这是唯一的构造函数,所以 @Autowired 注解可以省略
    public NotificationController(MessageService messageService) {
        System.out.println("NotificationController 正在被创建,注入 MessageService...");
        this.messageService = messageService;
    }

    @GetMapping("/notify")
    public String sendNotification() {
        // 4. 直接使用被注入的依赖
        return messageService.sendMessage("你好,世界!");
    }
}
第3步:运行 Spring Boot 应用

你的主启动类 DemoApplication.java 不需要任何改动。

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
运行与测试
  1. 启动 DemoApplication
  2. 在控制台,你会看到启动日志,其中应该包含我们打印的信息:
    NotificationController 正在被创建,注入 MessageService...
    
    这证明了 Spring 在创建 NotificationController 时调用了它的构造函数。
  3. 打开浏览器或使用 Postman/curl 访问 http://localhost:8080/notify
  4. 你会看到浏览器页面显示:
    邮件发送成功: 你好,世界!
    
  5. 同时,你的应用程序控制台会打印出:
    正在通过邮件发送消息: 你好,世界!
    

这整个过程完美地演示了构造函数注入。Spring 自动发现了 EmailServiceMessageService 的一个实现,并在创建 NotificationController 时,通过其构造函数将 EmailService 的实例注入了进去。


进阶:使用 Lombok 进一步简化

在实际项目中,如果依赖很多,手写构造函数会变得很繁琐。这时可以使用 Lombok 库来自动生成构造函数。

  1. 在你的 pom.xml 中添加 Lombok 依赖。

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
  2. 修改 NotificationController,使用 @RequiredArgsConstructor 注解。

    @RequiredArgsConstructor 会为所有 final 的字段,或者标记了 @NonNull 的字段,自动生成一个构造函数。

    package com.example.demo.controller;
    
    import com.example.demo.service.MessageService;
    import lombok.RequiredArgsConstructor; // 导入 Lombok 注解
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequiredArgsConstructor // 使用 Lombok 自动生成构造函数
    public class NotificationController {
    
        // Lombok 会为这个 final 字段生成构造函数参数
        private final MessageService messageService;
    
        // 你不再需要手写下面的构造函数了!
        /*
        public NotificationController(MessageService messageService) {
            this.messageService = messageService;
        }
        */
    
        @GetMapping("/notify")
        public String sendNotification() {
            return messageService.sendMessage("你好,世界!(来自Lombok)");
        }
    }
    

使用 Lombok 后,代码变得更加简洁,同时保留了构造函数注入的所有优点。这是目前 Spring Boot 项目中最流行和推荐的实践。