初识Lombok

news2024/11/19 3:17:12

前言

最近读一些公司的业务代码,发现近几年的java项目工程中都使用了lombok,lombok是一个可以自动生成get,set、toString等模板类方法的工具框架,程序再引入lombok后,添加一个注解便可以不写get\set\toString等方法。

Lombok示例

1、pom.xml中引入依赖

		<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.2.3</version>
        </dependency>

2、一个简单的pojo类

@Getter
@Setter
public class Student {

    private String name;
    private int age;
}

3、使用

 @Test
    public void test1(){

        Student student = new Student();
        student.setName("cz");
        student.setAge(12);
        System.out.println(student.getAge());
        System.out.println(student.getName());
    }

效果:
在这里插入图片描述

原理分析

通过以上测试案例可以看出,源码中并没有setName()和getName()方法,但是调用后并没有报错,反而运行成功了。那咱们大胆的猜测一下,会不会是在运行或者编译时动态的生成了代码?那么假设是运行时生成了代码,那大概率会使用到ASM或者其他字节码框架。但是这样编译阶段必然会报错,因为java是先编译后运行的。排除了第一种假设之后,我们只能按照第二种猜测来探究一下了。

首先从注解入手。

1、注解的种类

开发过程中经常用到注解,有时也会自定义注解,注解一般有两个重要的参数,一个是注解的作用域(Target)另一个是注解的保留策略(Retention),其中Retention有三个枚举分别如下:
1、SOURCE 表示注解只在源码阶段保留,编译成class后将不保留
2、CLASS 表示编译为class后也保留该注解,但是该注解运行时不能通过calzz.getAnnotation()获取到。
3、RUNTIME 表示class文件中保留该注解,同时也能使用getAnnotation获取到注解信息。

我在开发过程中一般使用的都是RUNTIME。
在这里插入图片描述

2、java编译器

《深入理解java虚拟机:JVM高级特性与最佳实践》这本书中描述了编译的几个关键步骤:
1、准备过程:初始化插入式注解处理器
2、解析与符号填充
3、插入式注解处理器的处理过程
4、分析与字节码的生成过程

其中上述的注解其实就是带有Retention(RetentionPolicy.SOURCE)保留策略的注解。Lombok的原理看到这里心里应该有了一个大概的认识了,lombok就是利用插入式注解同时自定义了注解处理器来干扰编译过程同时生成了目标代码。
在这里插入图片描述

3、java SPI机制

前文通过《深入理解java虚拟机》这本书了解到了lombok是如何通过注解来生成代码的,但是我还是有个疑问,lombok自定义的注解处理器是如何被程序找到并执行的呢? 答案就是Java的SPI机制。

SPI机制是JDK提供的一个服务发现机制,但是注意这里的服务发现机制并不是在分布式开发中接触到的类似zookeeper的服务注册和发现的中间件,而是一个针对本地interface接口的服务发现机制。下面用一个简单的例子展示一下。

3.1 编写接口
public interface TestSpiService {
   public void say();
}
3.2 编写实现类
public class TestSpiServiceImpl implements TestSpiService{

    @Override
    public void say() {

        System.out.println("我说了一句话");
    }
}
3.3 注册接口

注意图中的文件路径(META-INF/services)和文件名称(接口的全路径做为文件名称)和配置内容(接口实现类的全路径)在这里插入图片描述

3.4 接口调用
public class Main {

   public static void main(String[] args) {

       ServiceLoader<TestSpiService> loader = ServiceLoader.load(TestSpiService.class);
       for (TestSpiService spiService : loader) {
           spiService.say();
       }
   }
}

Lombok是如何指定自定义注解处理器的?

通过上述案例,我们发现可以通过配置文件的方式指定接口的实现类,同理JDK也是使用了这样的方式为自定义注解处理器提供了条件,再来看一下JDK中注解处理器准备阶段的源码(下图),从源码可以看到JDK也是使用了SPI机制来获取注解处理器。

在这里插入图片描述
看到这里我猜测lombok源码中也应该有一个META-INF/services文件夹同时在文件夹中存在avax.annotation.processing.Processor文件用来指定@Getter、@Setter等等自定义的注解处理器实现类。可是当我打开源码翻了所有的文件并没有找到META-INF文件夹。但是在一个构建脚本中发现了秘密,原来源码构建打包为jar包时在生成的jar包中才会生成该文件。
在这里插入图片描述
知道了自定义注解以及注解处理器的实现后,我又想到了JDK自带的几个注解,比如@Override(方法重写)会不会也是通过SPI来指定处理器处理的?其实JDK自带的几个注解并没有使用SPI机制实现,而是直接处理的。

在这里插入图片描述

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

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

相关文章

人工智能_CPU微调ChatGLM大模型_使用P-Tuning v2进行大模型微调_007_微调_002---人工智能工作笔记0102

这里我们先试着训练一下,我们用官方提供的训练数据进行训练. 也没有说使用CPU可以进行微调,但是我们先执行一下试试: https://www.heywhale.com/mw/project/6436d82948f7da1fee2be59e 可以看到说INT4量化级别最低需要7GB显存可以启动微调,但是 并没有说CPU可以进行微调.我们…

C语言中如何进行内存管理

主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《C语言》 C语言是一种强大而灵活的编程语言&#xff0c;但与其他高级语言不同&#xff0c;它要求程序员自己负责内存的管理。正确的内存管理对于程序的性能和稳定性至关重要。 一、引言 C 语言是一门广泛使用的编程语…

【算法历练】动态规划副本—路径问题

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;宙でおやすみ 1:02━━━━━━️&#x1f49f;──────── 2:45 &#x1f504; ◀️ ⏸ ▶️ ☰ &#…

现在在市场上云主机一般多少钱?影响其价格的因素有哪些

现在很多人都会购买云主机来帮助自己存储一些数据&#xff0c;但是很多人在购买云主机的时候最担心的就是云主机的价格。 由于很多人担心云服务器的价格会很高&#xff0c;因此一直在密切关注目前市场上各品牌云主机的相关价格。 下面就给大家详细介绍一下现在市场上一台云主机…

【DDD】学习笔记-领域驱动设计对持久化的影响

资源库的实现 如何重用资源库的实现&#xff0c;以及如何隔离领域层与基础设施层的持久化实现机制&#xff0c;具体的实现还要取决于开发者对 ORM 框架的选择。Hibernate、MyBatis、jOOQ 或者 Spring Data JPA&#xff08;当然也包括基于 .NET 的 Entity Framework、NHibernat…

若依Vue3:新一代前后端分离权限管理系统

若依Vue3&#xff1a;新一代前后端分离权限管理系统 随着技术的不断进步&#xff0c;前后端分离的开发模式逐渐成为主流&#xff0c;特别是在构建权限管理系统时。在这样的背景下&#xff0c;若依Vue3应运而生&#xff0c;作为基于Spring Boot、Spring Security、JWT、Vue3、V…

【C++】树形关联式容器set、multiset、map和multimap的介绍与使用

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.关联式容器 2.键…

二叉搜索树在线OJ题讲解

二叉树创建字符串 我们首先进行题目的解读&#xff1a; 大概意思就是用&#xff08;&#xff09;把每个节点的值给括起来&#xff0c;然后再经过一系列的省略的来得到最后的结果 大家仔细观察题目给出的列子就可以发现&#xff0c;其实这个题目可以大致分为三种情况&#xff1…

基于 LVGL 使用 SquareLine Studio 快速设计 UI 界面

目录 简介注册与软件获取工程配置设计 UI导出源码板级验证更多内容 简介 SquareLine Studio 是一款专业的 UI 设计软件&#xff0c;它与 LVGL&#xff08;Light and Versatile Graphics Library&#xff0c;轻量级通用图形库&#xff09;紧密集成。LVGL 是一个轻量化的、开源的…

[linux][xdp] xdp 入门

xdp 全称 eXpress Data Path&#xff0c;是 linux ebpf 中的一个功能。ebpf 在内核中预留了一些插入点&#xff0c;用户可以在这些插入点插入自己的处理逻辑&#xff0c;当数据路过插入点时可以做一些预期的处理&#xff0c;具体实现方式如下&#xff1a; ① 用户编写数据处理…

【C++私房菜】序列式容器的迭代器失效问题

目录 一、list的迭代器失效 二、vector的迭代器失效 1、空间缩小操作 2、空间扩大操作 三、总结 在C中&#xff0c;当对容器进行插入或删除操作时&#xff0c;可能会导致迭代器失效的问题。所谓迭代器失效指的是&#xff0c;原先指向容器中某个元素的迭代器&#xff0c;在…

尚硅谷webpack5笔记2

Loader 原理 loader 概念 帮助 webpack 将不同类型的文件转换为 webpack 可识别的模块。 loader 执行顺序 分类pre: 前置 loadernormal: 普通 loaderinline: 内联 loaderpost: 后置 loader执行顺序4 类 loader 的执行优级为:pre > normal > inline > post 。相…

在Node.js中如何实现用户身份验证和授权

当涉及到构建安全的应用程序时&#xff0c;用户身份验证和授权是至关重要的一环。在Node.js中&#xff0c;我们可以利用一些流行的库和技术来实现这些功能&#xff0c;确保我们的应用程序具有所需的安全性。本篇博客将介绍如何在Node.js中实现用户身份验证和授权。 用户身份验…

密码学系列(四)——对称密码2

一、RC4 RC4&#xff08;Rivest Cipher 4&#xff09;是一种对称流密码算法&#xff0c;由Ron Rivest于1987年设计。它以其简单性和高速性而闻名&#xff0c;并广泛应用于网络通信和安全协议中。下面是对RC4的详细介绍&#xff1a; 密钥长度&#xff1a; RC4的密钥长度可变&am…

精品springboot相亲网站预约

《[含文档PPT源码等]精品基于springboot相亲网站[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xff1a;HTML5,CSS3、Ja…

在Golang中简化日志记录:提升性能和调试效率

最大化效率和有效故障排除&#xff1a;在Golang中简化日志记录 日志记录是软件开发的一个基本方面&#xff0c;有助于调试、监控和理解应用程序的流程。在Golang中&#xff0c;有效的日志记录实践可以显著提高性能并简化调试过程。本文探讨了优化Golang日志记录的技术&#xf…

常用git 打tag命令

1.查看所有tag git tag 2.创建 v5.0.0的tag git tag v5.0.0 git tag &#xff08;创建后查看&#xff09; 3.推送到远程tag git push origin v5.0.0 4.删除远程tag git push origin --delete v5.0.0 5.删除本地tag git tag -d v5.0.0 6.添加带有备注信息的tag git tag v5.…

SpringCloud认识微服务

文章目录 1.1.单体架构1.2.分布式架构1.3.微服务1.4.SpringCloud1.5.总结 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 微服务架构是一种架构模式&…

Qcom camera hal简介

目录 背景 Android相机软件框架 Qcom HAL主要包括Camx和Chi两部分 Camx中Pipeline 和 node 下图是简单模型的pipeline (sensor --> IFE --> IPE --> SinkTarget) Pipeline中的buffer管理 IFE output port的buffer在Camx中申请 IPE output port使用的buffer来自…

JavaEE进阶(7)Spring Boot 日志(概述、用途、使用:打印日志,框架介绍,SLF4J 框架介绍、更简单的日志输出)

接上次博客&#xff1a;JavaEE进阶&#xff08;6&#xff09;SpringBoot 配置文件&#xff08;作用、格式、properties配置文件说明、yml配置文件说明、验证码案例&#xff09;-CSDN博客 目录 日志概述 日志的用途 日志使用 打印日志 在程序中获取日志对象 使用日志对象…