使用data注解报错_使用了这么久的lombok,你知道它的原理吗

Lombok是一个用于简化Java开发的工具,通过注解实现getter、setter等方法的自动创建,避免冗余代码。本文介绍了如何在IDEA中安装Lombok插件,引入依赖,并展示了@Data注解的使用。接着,文章探讨了Lombok的编译时增强原理,解释了其利用Java的Annotation Processing API在编译阶段生成额外代码。最后,简要说明了自定义注解处理器的实现步骤,并提到了处理报错的方法。

在日常的Java开发中,最常见的就是Javabean对象,常常一个对象中有很多,私有属性,我们需要进行setter和getter的操作,如下

public class Student {        private Integer id;        private String name;        private Integer age;        private Integer sex;        private String address;        private Float score;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public Integer getSex() {        return sex;    }    public void setSex(Integer sex) {        this.sex = sex;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }    public Float getScore() {        return score;    }    public void setScore(Float score) {        this.score = score;    }}

这样的代码,显得很臃肿,尤其是当我们再添加属性,或者修改属性名称时,都需要手动更改或新增setter和getter方法,维护起来比较麻烦,因此很多开发者在日常使用过程中,都使用lombok工具来简化相关代码,代码如下

@Datapublic class Student {    private Integer id;    private String name;    private Integer age;    private Integer sex;    private String address;    private Float score;}

lombok工具常见使用方法

以idea举例,我们使用lombok首先需要安装lombok插件,如下图

e4d6b957a940ae7daa2db7be3f31b1f7.png

然后在使用的项目中引入依赖(以maven举例)

<dependency>    <groupId>org.projectlombokgroupId>    <artifactId>lombokartifactId>    <version>1.18.12version>    <scope>providedscope>dependency>

接下来我们就可以使用lombok工具提供的注解功能,进行开发。下面对常见的lombok工具注解进行介绍:

@Getter // 生成getter方法@Setter // 生成setter方法@ToString // 自动重写 toString() 方法,会印出所有变量@EqualsAndHashCode // 自动生成equals和hashcode方法@NoArgsConstructor // 生成一个没有参数的构造器@AllArgsConstructor // 生成一个包含所有参数的构造器@RequiredArgsConstructor // 生成一个包含 "特定参数" 的构造器(特定参数指的是那些有加上 final 修饰词的变量们)@Data //这个注解,等于同时加了@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor注解@Builder // 自动生成流式 set 值写法@Slf4j //自动生成该类的 log 静态常量,直接通过log写日

如下图

bfbfe9e2845ca170eda0dc1d7f99c213.png

为什么使用了注解就可以做到这些功能?

对于代码增强,一般有两种方式,一种运行时增强,例如spring的aop,在运行时,对代码做功能增强;另一种是编译器增强,即编译时,通过字节码技术,将相应的代码植入到class中,lombok就采用两编译器增强。

上面我们对student这个类,加入@Data注解,编译后,我们查看下class文件,发现getter方法、setter方法、tostring方法等都写了相关代码,如下图

6f853780591590c46f71b9876b7a060e.png

eba35f4afd643b6a4dcd615fb5dec256.png

原理

针对运行期增强,一般基于动态代理、反射技术实现,性能相对损耗大;编译器增强,一般基于Annotation Processing Tool(APT技术在JDK8中已经彻底删除)以及Pluggable Annotation Processing API技术。

因此我们主要看看Pluggable Annotation Processing API技术,自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。

插件化注解处理API的使用步骤大概如下:

1、自定义一个Annotation Processor,需要继承javax.annotation.processing.AbstractProcessor,并覆写process方法。2、自定义一个注解,注解的元注解需要指定@Retention(RetentionPolicy.SOURCE)。3、需要在声明的自定义Annotation Processor中使用javax.annotation.processing.SupportedAnnotationTypes指定在第2步创建的注解类型的名称(注意需要全类名,"包名.注解类型名称",否则会不生效)。4、需要在声明的自定义Annotation Processor中使用javax.annotation.processing.SupportedSourceVersion指定编译版本。5、可选操作,可以通在声明的自定义Annotation Processor中使用javax.annotation.processing.SupportedOptions指定编译参数。6、通过服务注册指定,META-INF/services/javax.annotation.processing.Processor文件中添加 前面定义AnnotationProcessor

下面我们按照上面步骤来演示一下:

自定义注解解析器(此处可以通过asm字节码技术写入新方法等,本文不介绍字节码技术,有兴趣的可以研究)

@SupportedAnnotationTypes(value = {"com.example.demo.plugin.Demo"})@SupportedSourceVersion(value = SourceVersion.RELEASE_8)public class AnnotationProcessor extends AbstractProcessor {    @Override    public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {        System.out.println("Log in AnnotationProcessor.process");        for (TypeElement typeElement : annotations) {            System.out.println(typeElement);        }        System.out.println(roundEnv);        return true;    }}

自定义注解

@Retention(RetentionPolicy.SOURCE)@Target(ElementType.TYPE)public @interface Demo {}

使用spi注入注解解析器

655dd3122d2556b4dae109e30d3f73d2.png

使用注解

5ff71ba82a2654995cfdd1270ef74ece.png

编写测试用例

public class App {    public static void main( String[] args )    {        System.out.println( "Hello World!" );        Student student = new Student();    }}

运行结果如下,可以看到编译期AnnotationProcessor生效了

Log in AnnotationProcessor.processcom.example.Demo[errorRaised=false, rootElements=[com.example.Demo, com.example.App, com.example.Student], processingOver=false]Log in AnnotationProcessor.process[errorRaised=false, rootElements=[], processingOver=true]

注意:如果出现下列报错,可以将AnnotationProcessor先编译,或者放到jar中即可。

[ERROR] Bad service configuration file, or exception thrown whileconstructing Processor object: javax.annotation.processing.Processor: Provider com.example.demo.plugin.AnnotationProcessor not found

Lombok便是通过Pluggable Annotation Processing API来实现代码生成的。

根据上面的原理,我们查看下lombok源码,发现的确如此

6a4f04fc6aa5813c68667a8d15651363.png

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值