我们来详细讲解一下在 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 {@Overridepublic 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 项目中最流行和推荐的实践。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87989.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87989.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87989.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.6.30-2025.7.06第26周:第一次参加头马演讲俱乐部

现在是周一早上6:23&#xff0c;我开始写上周的周总结。 3件超出预期的事 参加头马俱乐部绝对是最超出预期的&#xff0c;使得这个周末格外的快乐简历的第一版终于改完了&#xff0c;花了好长的时间&#xff0c;其中有一天心情还很荡&#xff0c;因为&#xff0c;我想&#x…

2025使用VM虚拟机安装配置Macos苹果系统下Flutter开发环境保姆级教程--下篇

其实如何安装VM,如何安装MACOS网上的教程很多,我只是结合我的体验重新整理了一次,接下来才进入本教程最核心的部分,Flutter开发环境的配置部分。、一.配置前准备 主要是准备相应的工具包,以及其他虚拟机设置1.工具包 工具包的版本也可以自行配置,我这主要是我使用的是F…

QSPI、OSPI与FSMC的区别与内存映射分析

QSPI、OSPI与FSMC的区别与内存映射分析 基本概念与区别 1. FSMC (灵活静态存储控制器) 接口类型&#xff1a;并行接口&#xff0c;通常8/16位数据总线总线标准&#xff1a;传统并行总线协议速度&#xff1a;相对较低&#xff0c;通常最高约100MHz应用场景&#xff1a;SRAM、NOR…

系统思考与心智模式探索

成长的真正障碍&#xff0c;不是能力的不足&#xff0c;而是看待问题的局限。 在复杂多变的商业环境中&#xff0c;我们往往习惯于解决“眼前”的问题&#xff0c;却忽视了深藏背后的系统性障碍。我们看到的只是表面的“症状”&#xff0c;而真正的根源&#xff0c;却往往隐藏…

物联网技术的关键技术与区块链发展趋势的深度融合分析

一、物联网技术的核心架构与关键技术 物联网技术体系由感知层、网络层、平台层、应用层和安全层构成&#xff0c;各层技术协同工作&#xff0c;实现物理世界与数字世界的深度融合。 感知层&#xff1a;物联网的“感官” 传感器技术&#xff1a;包括环境传感器&#xff08;温度…

针对Exhcnage Server的攻击防范措施

一、背景介绍最近&#xff0c;安全研究人员揭露了一个名为 NightEagle&#xff08;又名 APT-Q-95&#xff09; 的高级持续性威胁&#xff08;APT&#xff09;组织。这个组织被观察到利用 Microsoft Exchange 服务器中的零日漏洞链 进行攻击&#xff0c;其主要目标是中国政府、国…

编程基础:继承

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录继承&#xff1a;使用基类成员&#xff1a;前提——派生类必须同样支持基类成员(组件和功能)示例&#xff1a;动物Animal 有 鳃 和 会飞。则 鸟Bird 不是 Animal&#xff0c;因为Bird虽会飞&#xff0c;却没有鳃。鱼…

TMC4361A 使用(未验证)

prompt 我用STM32F103C8T6 来控制 TMC4361A 运动控制芯片 &#xff0c;我配置 STM32F103C8T6 的 SPI1 与 TMC4361A 进行通信&#xff0c;配置 PA4 作为片选线&#xff0c;配置 PA8 作为 RCC_MCO 输入时钟输入到 TMC4361A, 并将其连接到TMC4361A的CLK_EXT引脚。我想控制 TMC4361…

深度剖析:如何解决Node.js中mysqld_stmt_execute参数错误

在Node.js后端开发中&#xff0c;使用mysql2等数据库驱动与MySQL/MariaDB交互时&#xff0c;Incorrect arguments to mysqld_stmt_execute 是一个令人头疼的错误。它通常意味着你传递给SQL预处理语句的参数数量与SQL字符串中问号&#xff08;?&#xff09;占位符的数量不匹配。…

Vue3 学习教程,从入门到精通,Vue 3 安装指南及语法知识点详解(2)

Vue 3 安装指南及语法知识点详解 本文将详细介绍 Vue 3 的所有安装方式&#xff0c;并深入讲解 Vue 3 的语法知识点。此外&#xff0c;还将提供一些综合性案例&#xff0c;展示如何综合运用 Vue 3 的各项功能。一、安装 Vue 3 的所有方式 Vue 3 提供了多种安装方式&#xff0c;…

C++基础复习笔记

一、数组定义 在C中&#xff0c;数组初始化有多种方式&#xff0c;以下是常见的几种方法&#xff1a; 默认初始化 数组元素未显式初始化时&#xff0c;内置类型&#xff08;如int、float&#xff09;的元素值未定义&#xff08;垃圾值&#xff09;&#xff0c;类类型调用默认构…

手机和PC远控安全深度测评:TeamViewer/ToDesk/向日葵安全防线对比

声明&#xff1a;本测试报告系作者基于个人兴趣及使用场景开展的非专业测评&#xff0c;测试过程中所涉及的方法、数据及结论均为个人观点&#xff0c;不代表任何官方立场或行业标准。 一、引言 当下远程控制技术已深度融入大众的工作与生活&#xff0c;无论是上班族在家操…

Windows 11的开始菜单调整为左下角布局

1.桌面右键个性化 2.个性化中任务栏 3.任务栏选择任务栏行为 4.任务栏行为中 任务栏对齐方式选择靠左即可

Go语言项目工程化 — 常见开发工具与 CI/CD 支持

在Go语言的项目工程化实践中&#xff0c;常见开发工具与 CI/CD 支持是保障团队协作、高效交付与项目质量的关键。以下是第 68 章的详细内容。一、开发辅助工具Go语言生态为开发者提供了丰富的工具&#xff0c;以提高代码质量与开发效率。1. 格式化与静态检查工具说明gofmt标准格…

OpenCV人脸分析------绘制面部关键点函数drawFacemarks()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于在图像上绘制面部关键点&#xff08;facial landmarks&#xff09;&#xff0c;例如使用 FacemarkLBF, FacemarkKazemi 等算法检测到的…

Linux内核ext4 extent:解决大文件存储难题的关键

在Linux 操作系统的庞大生态中&#xff0c;文件系统犹如一座城市的基础设施&#xff0c;支撑着数据的有序存储与高效访问。而 ext4 文件系统&#xff0c;作为 Linux 文件系统家族中的重要一员&#xff0c;自诞生起便凭借诸多先进特性备受瞩目。其中&#xff0c;extent 机制堪称…

reactnative页面适配UI设计尺寸px转dp的完美解决方案px2dp精要篇

你的 px2dp 函数基本思路是正确的&#xff0c;但可以进一步优化以确保更精确的适配。以下是改进后的完美精确方案&#xff1a; 完美精确的适配方案 import { Dimensions, PixelRatio, Platform, ScaledSize } from react-native;// 获取屏幕尺寸&#xff08;考虑横竖屏&#…

【世纪龙科技】汽车钣金虚拟仿真教学实训软件

在汽车后市场人才紧缺的当下&#xff0c;职业院校汽车钣金教学却长期面临“三难困境”&#xff1a;实训设备昂贵且损耗快、学生实操机会稀缺、教学评价依赖主观经验。江苏世纪龙科技公司以十余年汽车教育数字化积淀为基石&#xff0c;推出《汽车钣金教学软件》&#xff0c;通过…

Fiddler中文版抓包工具在后端API调试与Mock中的巧用

在现代开发中&#xff0c;前后端往往分属不同小组甚至不同公司&#xff0c;接口联调变得至关重要。尤其是在多团队合作、后端接口尚未完成或频繁变动的项目中&#xff0c;前端开发进度容易被阻碍。此时&#xff0c;通过灵活运用 Fiddler抓包工具&#xff0c;前端可以在后端接口…

基于 Flask框架开发的轻量级招聘网站

简单的招聘网站示例 这是一个基于 Flask 框架开发的轻量级招聘网站示例&#xff0c;采用 Jinja2 模板引擎和 Bootstrap 前端框架&#xff0c;模仿 拉勾网 风格&#xff0c;实现了招聘平台的核心功能。系统支持 个人用户 和 企业用户 两种角色&#xff0c;个人用户可以浏览职位、…