初识Lombok

前言

最近读一些公司的业务代码,发现近几年的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机制实现,而是直接处理的。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UDP 与 TCP 的区别是什么?

目录 区别 一、面向无连接 二、不可靠性 三、高效 四、传输方式 五、适用场景 1.直播 2.英雄联盟 六、总结 区别 首先 UDP 协议是面向无连接的&#xff0c;也就是说不需要在正式传递数据之前先连接起双方。然后 UDP 协议只是数据报文的搬运工&#xff0c;不保证有序且…

Kotlin多线程

目录 线程的使用 线程的创建 例一&#xff1a;创建线程并输出Hello World Thread对象的用法 start() join() interrupt() 线程安全 原子性 可见性 有序性 线程锁 ReentrantLock ReadWriteLock 线程的使用 Java虚拟机中的多线程可以1:1映射至CPU中&#xff0c;即…

【Java程序设计】【C00313】基于Springboot的物业管理系统(有论文)

基于Springboot的物业管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的物业管理系统&#xff0c;本系统有管理员、物业、业主以及维修员四种角色权限&#xff1b; 管理员进入主页面&#xff0c;主要功能包…

MCU独立按键单控LED实现

##江科大视频学习&#xff0c;并且对具体的一些小细节进行更详细的分析。 什么是独立按键&#xff1f; 轻触按键:相当于是一种电子开关&#xff0c;按下开头接通&#xff0c;松开时开头断开&#xff0c;实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。 注意…

Keepalived介绍、架构和安装

Keepalived介绍、架构和安装 文章目录 Keepalived介绍、架构和安装1.Keepalived&#xff08;高可用性服务&#xff09;1.1 Keepalived介绍1.2 Keepalived 架构1.3 Keepalived 相关文件 2.Keepalived安装2.1 主机初始化2.1.1 设置网卡名和ip地址2.1.2 配置镜像源2.1.3 关闭防火墙…

在autodl搭建stable-diffusion-webui+sadTalker

本文介绍在autodl.com搭建gpu服务器&#xff0c;实现stable-diffusion-webuisadTalker功能&#xff0c;图片音频 可生成视频。 autodl租GPU 自己本地部署SD环境会遇到各种问题&#xff0c;网络问题&#xff08;比如huggingface是无法访问&#xff09;&#xff0c;所以最好的方…

元学习(meta-learning)的通俗解释

目录 1、什么是元学习 2、元学习还可以做什么 3、元学习是如何训练的 1、什么是元学习 meta-learning 的一个很经典的英文解释是 learn to learn&#xff0c;即学会学习。元学习是一个很宽泛的概念&#xff0c;可以有很多实现的方式&#xff0c;下面以目标检测的例子来解释…

macOS系统下载IDEA的操作流程

第一步 进入官网 Download IntelliJ IDEA – The Leading Java and Kotlin IDE 第二步 根据mac的芯片选择版本下载 芯片的查看位置是【设置】-【通用】-【关于本机】-第二个&#xff0c;我的是Apple芯片&#xff0c;选Apple Silicon -- 第三步 右上角下载处打开安装包&…

485隔离器4口集线器一分二四路导轨安装数字量输入模块RS485中继

品牌&#xff1a;泰工华控 型号&#xff1a;TD-7511/TD-7512/TD-7514 产地&#xff1a;中国大陆 省份&#xff1a;安徽省 地址&#xff1a;宿州市 颜色分类&#xff1a;485一进一出隔离,485缓存器一进二出&#xff08;两主一从,485分路器一进二出&#xff08;一主两从&…

[C++][C++11][四] -- [lambda表达式]

目录 1.为什么要有lambda表达式&#xff1f;2.lambda表达式3.lambda表达式语法4.函数对象与lambda表达式 1.为什么要有lambda表达式&#xff1f; 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法 如果待排序元素为自定义类型&am…

<网络安全>《52 网络攻防专业课<第十五课 - 跳板>

1 跳板技术 当攻击者入侵被攻击者时&#xff0c;被攻击者可以根据IP地址追踪攻击者来自哪里。 攻击者为了隐藏自己的真正IP&#xff0c;通常会采用跳板&#xff0c;如右图&#xff0c; 攻击者通过2个跳板攻击被攻击者。即使被攻击者进行反向追踪&#xff0c;也只能追踪到攻击…

【Activiti7系列】Activi7简介和基于Spring Boot整合Activiti7(流程设计器)

本文将介绍Activiti7基础概念及基于Spring Boot整合Activiti7(流程设计器)的具体步骤。 作者&#xff1a;后端小肥肠 1. 前言 在企业级应用中&#xff0c;业务流程的管理和执行是至关重要的一环。Activiti7是一个强大的开源工作流引擎&#xff0c;它提供了灵活的流程定义、任务…

机器学习.线性回归

斯塔1和2是权重项&#xff0c;斯塔0是偏置项&#xff0c;在训练过程中为了使得训练结果更加精确而做的微调&#xff0c;不是一个大范围的因素&#xff0c;核心影响因素是权重项 为了完成矩阵的运算&#xff0c;在斯塔0后面乘x0&#xff0c;使得满足矩阵的转换&#xff0c;所以在…

HTTP---------状态码

当服务端返回 HTTP 响应时&#xff0c;会带有一个状态码&#xff0c;用于表示特定的请求结果。比如 HTTP/1.1 200 OK&#xff0c;里面的 HTTP/1.1 表示协议版本&#xff0c;200 则是状态码&#xff0c;OK 则是对状态码的描述。 由协议版本、状态码、描述信息组成的行被称为起始…

文献阅读:Transformers are Multi-State RNNs

文献阅读&#xff1a;Transformers are Multi-State RNNs 1. 内容简介2. 方法介绍 1. 基础回顾 1. RNN2. Transformer 2. Transformer解构 1. MSRNN2. Transformer 3. TOVA 1. 现有转换策略2. TOVA 3. 实验考察 & 结论 1. 实验设计2. 实验结果 1. LM2. 长文本理解3. 文本生…

win7系统安装.net 4.7.2失败的解决办法

1、提示如下错误时导入证书MicrosoftRootCertificateAuthority2011.cer&#xff0c;具体可以从网上搜&#xff1a; 2、导入证书后再次重试&#xff0c;提示如下错误&#xff1a; 这时可能是缺少系统补丁&#xff0c;安装补丁&#xff1a;Windows6.1-KB2813430-x64.msu。安装完要…

Seata分布式事务实战XATCC模式

目录 XA模式 XA 模式的使用 Spring Cloud Alibaba整合Seata XA TCC模式 TCC模式接口改造 TCC如何控制异常 Spring Cloud Alibaba整合Seata TCC XA模式 整体机制 在 Seata 定义的分布式事务框架内&#xff0c;利用事务资源&#xff08;数据库、消息服务等&#xff09;对…

力扣--哈希表/滑动窗口/双指针3.无重复字符的最长子串

思路分析&#xff1a; 使用双指针 i 和 j 表示子串的起始位置和结束位置。遍历字符串 s&#xff0c;对于每个字符&#xff1a; 如果字符不在 hash 中&#xff0c;将其加入 hash&#xff0c;同时更新最长子串的长度 result。如果字符已经在 hash 中&#xff0c;说明有重复字符出…

力扣LCR 140. 训练计划 II(顺序遍历,快慢指针)

Problem: LCR 140. 训练计划 II 文章目录 题目描述思路复杂度Code 题目描述 思路 思路1&#xff1a;顺序遍历 欲返回倒数第cnt个节点则需要顺序遍历到len-cnt&#xff08;其中len为链表的长度&#xff09; 思路2&#xff1a;快慢指针 让一个快指针fast指向cnt 1个节点&#x…

Java的File常用方法【详解】

目录 1.概念 2.创建对象 3.常用方法1&#xff1a;判断文件类型、获取文件信息 4.常用方法2&#xff1a;创建文件、删除文件 5.常用方法3&#xff1a;遍历文件夹 1.概念 File是java.io.包下的类&#xff0c; File类的对象&#xff0c;用于代表当前操作系统的文件&#xff0…