从零开始 Spring Boot 38:Lombok 与依赖注入

news2024/10/5 17:22:29

从零开始 Spring Boot 38:Lombok 与依赖注入

spring boot

图源:简书 (jianshu.com)

在之前的文章中,我详细介绍了 Lombok 的用法,考虑到在 Spring 中使用依赖注入(DI)是如此的频繁,因此有必要讨论使用 Lombok 时可能对依赖注入造成的影响。

我们都知道,Spring 中的依赖注入分为三种情况:

  • 通过属性进行依赖注入。
  • 通过构造器进行依赖注入。
  • 通过 Setter 进行依赖注入。

通过属性进行依赖注入并不会影响我们使用 Lombok,比如:

@RestController
@RequestMapping("/hello")
@Validated
@AllArgsConstructor
public class HelloController {
    @Autowired
    private FibonacciService fibonacciService;

    @GetMapping
    public Result<?> hello(@RequestParam @Min(1) @NotNull Integer n) {
        int fibonacci = fibonacciService.fibonacci(n);
        return Result.success(fibonacci);
    }
}

**无论我们有没有使用构造器注入,用@Autowired标记的属性都会在 bean 实例创建后被 Spring 通过反射来完成注入。**因此实际上这里 Lombok 的@AllArgsConstructor注解生成的构造器并不会对属性fibonacciService的注入产生影响。

构造器注入

下面我们看构造器注入时的情形。

一般的,我们可以将属性设置为final,并借助 Lombok 的@RequiredArgsConstructor注解对需要的属性进行构造器注入:

@RestController
@RequestMapping("/hello")
@Validated
@RequiredArgsConstructor
public class HelloController {
    private final FibonacciService fibonacciService;

    @GetMapping
    public Result<?> hello(@RequestParam @Min(1) @NotNull Integer n) {
        int fibonacci = fibonacciService.fibonacci(n);
        return Result.success(fibonacci);
    }
}

我们知道,在 Spring 的后期版本中,只有一个构造器的情况下是不需要用@Autowired来标记构造器的,Spring 默认会使用这个唯一的构造器进行注入。而在这个示例中,@RequiredArgsConstructor会为我们创建一个包含所有final的非静态属性的构造器,而 Spring 将用这个构造器完成注入。

我们看到,只有一个构造器时(无论是自己编写的还是 Lombok 自动生成的),都不会产生影响,但如果有多个构造器呢?

看下面这个示例:

@RestController
@RequestMapping("/hello")
@Validated
@RequiredArgsConstructor
public class HelloController {
    private final FibonacciService fibonacciService;
    private final Integer n;

    @Autowired
    public HelloController(FibonacciService fibonacciService) {
        this(fibonacciService, 10);
    }

    @GetMapping
    public Result<?> hello(@RequestParam String n) {
        int numN;
        if ("null".equals(n)) {
            numN = this.n;
        } else {
            numN = Integer.parseInt(n);
        }
        if (numN < 1) {
            return Result.fail("hello.input.invalid", "n 不能小于 1");
        }
        int fibonacci = fibonacciService.fibonacci(numN);
        return Result.success(fibonacci);
    }
}

在这个示例中,实际上字节码中会有两个构造器,一个是我们自己编写的有一个参数的构造器,另一个是 Lombok 生成的有两个参数的构造器。

注意,在自己编写的构造器中,我们使用this(...)调用了 Lombok 创建的构造器。

此时如果我们想通过构造器对属性fibonacciService进行注入,就需要告诉 Spring 框架该用哪个构造器完成注入。比较简单的是,如果要用于注入的构造器是我们自己编写的(就像示例中的),我们只需要使用@Autowired标记相应的构造器即可。

如果是反过来,就会有一点麻烦:

@RestController
@RequestMapping("/hello")
@Validated
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class HelloController {
    private final FibonacciService fibonacciService;
    private Integer n = 10;

    public HelloController(FibonacciService fibonacciService, Integer n) {
        this.fibonacciService = fibonacciService;
        this.n = n;
    }

	// ...
}

注意,这里的属性n被修改为非final的。

现在,@RequiredArgsConstructor(onConstructor = @__(@Autowired))将在HelloController类的字节码中生成一个带@Autowired标记的构造器用于注入:

@RestController
@RequestMapping({"/hello"})
@Validated
public class HelloController {
    // ...
    @Autowired
    public HelloController(final FibonacciService fibonacciService) {
        this.fibonacciService = fibonacciService;
    }
}

也就是说,我们可以在 Lombok 用于生成构造器的相应注解中,通过onConstructor属性来指定一系列注解,让 Lombok 在生成构造器时在构造器上添加上这些注解。

这种写法(@__(@Autowired)))有些奇怪,实际上@__是一个并不存在的注解,可以用它来包裹一个注解列表(逗号分隔)来为构造器指定多个用于生成时添加的注解。

Setter 注入

我们知道,在使用 Setter 注入时,必须要使用@Autowired注解。同样的,可以用类似的方式让 Lombok 生成 Setter 时添加上相应的注解:

@RestController
@RequestMapping("/hello")
@Validated
public class HelloController {
    @Setter(onMethod = @__(@Autowired))
    private FibonacciService fibonacciService;
    private final Integer n = 10;
    
    @GetMapping
    public Result<?> hello(@RequestParam String n) {
        // ...
    }
}

The End,谢谢阅读。

这篇文章相对来说简短很多,算是对之前的文章的一个补充。

本文所有的示例代码可以通过这里获取。

参考资料

  • Constructor Injection in Spring with Lombok | Baeldung

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

精通postman教程(五)postman请求参数化

作为一名测试工程师&#xff0c;那么Postman绝对是大伙必备的工具之一。 在这个系列教程中&#xff0c;我将为大伙详细讲解如何使用Postman进行API测试。 今天我带大伙实战一番postman如何请求参数化 &#xff0c;让你们快速上手这款工具。 请求参数化 数据参数化是Postman…

Kivy系列(一)—— Kivy buildozer的Docker镜像制作

接触Kivy是奔着使用python便捷又是跨平台工具去的&#xff0c;如此一套代码可以发布为各类平台的成果。但是由于网络环境限制&#xff0c;以及kivy工具链上各类工具的频繁迭代&#xff0c;即使按照github上的kivy buildozer官方文档&#xff0c;也很难打包成功&#xff0c;kivy…

调试笔记-stm32的OTA/IAP 通过485升级固件

背景&#xff1a;最近需要在stm32上实现通过rs485升级固件功能。经过几天搜索和调试&#xff0c;实现了功能。 目标&#xff1a;使用cubeIDE实现stm32F407VGT6&#xff0c;通过RS485升级固件 调试记录&#xff1a; 步骤1. 在keil环境下的rs485升级固件(含源码)&#xff1a;S…

react 18.2 官网学习笔记(1)

useMemo const cachedValue useMemo(calculateValue, dependencies)&#xff1b;参数一&#xff1a;计算要缓存的值的函数。它应该是纯的&#xff0c;不应该接受任何参数&#xff0c;并且应该返回任何类型的值。React会在初始渲染时调用你的函数。在下一次渲染时&#xff0c;…

从搭建hadoop开始学习大数据中分而治之的MapReduce(伪集群模式)

环境准备 首先需要将如下四个必要的文件下载到计算机&#xff08;已经附上了下载地址&#xff0c;点击即可下载&#xff09;。 Vmware Workstation 17.x 【官方的下载地址】 CentOS-7-x86_64-Minimal-2009【阿里云镜像站下载地址】 openjdk-8u41-b04-linux-x64-14_jan_2020【开…

入栏需看——全国硕士研究生入学统一考试管理类专业学位联考

本栏意在收集关于全国硕士研究生入学统一考试管理类专业学位联考&#xff0c;简称管理类联考的知识点&#xff0c;考点&#xff0c;希望大家一起沟通&#xff0c;一起进步&#xff0c;管它贵不贵&#xff0c;考过了再说咯 英语 知识篇 阅读 完型填空 作文 技巧篇 第二章…

rolling的用法实例

在数据分析的过程中&#xff0c;经常用到对计算移动均值&#xff0c;使用rolling可以轻松实现这个功能~ rolling函数是一个用于时间序列分析的函数&#xff1b; 一、参数解析 首先&#xff0c;让我们来了解一下rolling的各个参数吧 DataFrame.rolling(window, min_periodsN…

Echarts—X轴鼠标滑动或者缩放/多列柱状图中某一列数据为0时不占位

这里写目录标题 需求背景图表展示X轴鼠标滑动或者缩放设置多列柱状图中某一列数据为0时不占位图表代码展示 需求背景 用柱状图展示12个月的项目对应的供应商数据&#xff1b;每个月有多个项目不确定&#xff0c;1-50之间&#xff0c;也就是说&#xff0c;12个月&#xff0c;每…

1.数据库的基本操作

SQL句子中语法格式提示&#xff1a; 1.中括号&#xff08;[]&#xff09;中的内容为可选项&#xff1b; 2.[&#xff0c;...]表示&#xff0c;前面的内容可重复&#xff1b; 3.大括号&#xff08;{}&#xff09;和竖线&#xff08;|&#xff09;表示选择项&#xff0c;在选择…

魏可伟受邀参加 2023 开放原子全球开源峰会

6月11日-13日&#xff0c;2023 开放原子全球开源峰会在京举行。作为开源行业年度盛事&#xff0c;本次峰会以“开源赋能&#xff0c;普惠未来”为主题&#xff0c;聚集政、产、学、研等各领域优势&#xff0c;汇聚顶尖大咖&#xff0c;共话开源未来。 KaiwuDB CTO 魏可伟受邀出…

Rancher的安装(k8s)

1、 Rancher概述 rancher官方文档 Rancher 是一个 Kubernetes 管理工具&#xff0c;让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托管服务提供商的集群&#xff0c;创建节点并安装 Kubernetes&#xff0c;或者导入在任何地方运行的现有…

【总结笔记】Spring

1 Spring容器加载配置文件进行初始化。 Spring容器加载配置文件进行初始化主要有两种形式&#xff1a; 加载配置文件进行初始化&#xff1a; ClassPathXmlApplicationContext ctx new ClassPathXmlApplicationContext(“ApplicationContext.xml”); 加载配置类进行初始化&…

测试人如何打造简历化思维?三年经验软件测试简历分析

测试人如何打造简历化思维&#xff1f;如题&#xff0c;不是写如何打造简历&#xff0c;而是简历化思维&#xff0c;如何理解简历化思维&#xff1f; 很多人跟我说很累&#xff0c;不想干了&#xff0c;每天忙忙碌碌在给老板打工&#xff0c;年底老板又可以换法拉利了。 玩笑…

【探索 Kubernetes|容器基础进阶篇 系列 4】理解现代云原生时代的引擎

文章目录 系列文章目录&#x1f479; 关于作者一、前言|回顾二、静态和动态视图三、爆火的容器编排工具 Kubernetes 的诞生四、Kubernetes 要解决的问题是什么&#xff1f;五、理解 Kubernetes 全局架构图Master&#xff08;控制节点&#xff09;Node&#xff08;计算节点&…

Go语言小细节

Go语言小细节 结构体 结构体中允许存在匿名字段&#xff0c;即只有类型没有具体的变量名&#xff0c;但是一个结构体内只允许有一个相同类型的结构体中字段大写开头表示可公开访问&#xff0c;小写表示私有&#xff08;仅在当前结构体的包中可访问&#xff09;在编写结构体的…

Linux之进程信号(下)

文章目录 前言信号的相关概念一、信号的保存——位图1.内核中的表示2.信号集——sigset_t3.信号集操作函数 二、信号的捕捉过程1.内核态和用户态用户代码和内核代码如何分辨是用户态还是内核态一个进程如何跑到OS中执行方法 2.信号捕捉的过程 三、核心转储1.数组越界并不一定会…

CTFHub | 远程包含

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

Flutter 库:提升开发体验——Quick

Flutter 库&#xff1a;提升开发体验——Quick 文章目录 Flutter 库&#xff1a;提升开发体验——Quick一、概述1、简介2、功能3、官方资料4、思考 二、基本使用1、安装2、基本使用3、运行结果 三、List 列表扩展示例四、Map 映射扩展示例五、其它示例 一、概述 1、简介 Quic…

打印杨辉三角

这个公式&#xff0c;不好算&#xff0c;我觉得还是杨辉三角算起来方便&#xff1a;c#代码如下&#xff1a; double 打印杨辉三角(int n)//n必须是偶数&#xff0c;展开项是n1&#xff0c;中间项是n/2,此处返回中间项的概率202306131722 { //for (int i 0…

3个月面过字节测开岗,拿个20K不过分吧?

计算机专业&#xff0c;代码能力一般&#xff0c;之前有过两段实习以及一个学校项目经历。第一份实习是大二暑期在深圳的一家互联网公司做前端开发&#xff0c;第二份实习由于大三暑假回国的时间比较短&#xff08;小于两个月&#xff09;&#xff0c;于是找的实习是在一家初创…