精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

用了那么久的 Lombok,你知道它的原理么?

開發 新聞
我們學會了如何自己寫一個屬于自己的簡易Lombok的插件。

序言

在寫Java代碼的時候,最煩寫setter/getter方法,自從有了Lombok插件不用再寫那些方法之后,感覺再也回不去了,那你們是否好奇過Lombok是怎么把setter/getter方法給你加上去的呢?有的同學說我們Java引入Lombok之后會污染依賴包,那我們可不可以自己寫一個工具來代替Lombok呢?

知識點

  • Java編譯過程
  • 了解Lombok原理
  • 了解插入式注解處理器

分析

序言提到的問題其實都是同一個問題,就是如何去獲取和修改Java源代碼?

要回答這個問題,我們需要回答這幾個問題:

  1. Java編譯器是如何解析Java源代碼的?
  2. 編譯器編譯源代碼都有哪些步驟?
  3. 我們在編譯器工作的時候,怎么才能去增加內容或者是進行代碼分析?

希望大家看完本文能夠自己寫一個簡易的Lombok工具。

回答

如何解析源代碼

其實從我們的代碼到被編譯,中間隔了一個數據結構,叫做AST(抽象樹)。具體的形式,可以查看下面的圖片。右邊的便是AST的數據結構了。

代碼編譯都有哪些步驟

整個編譯過程大致如下:

圖片來自 openjdk

1、初始化插入注解處理器

2、解析與填充符號表過程

a.詞法分析、語法分析。將源代碼的字符流轉變為標記集合,構造出抽象語法樹。

b.填充符號表。產生符號地址和符號信息。

3、插入式注解處理器的注解處理過程:插入式注解處理器的執行階段。后面我會給大家帶來兩個此方面的實用實戰例子。

4、分析與字節碼生成過程

a.標注檢查。對語法的靜態信息檢查。

b.數據流及控制流分析。對程序動態運行過程進行檢查。

c.解語法糖。將簡化代碼編寫的語法糖還原為原有的形式。

d.字節碼生成。將前面各個步驟所生成的信息轉化成為字節碼。

?我們知道了上面的理論之后,接下來我們進行實戰。帶著大家一起去修改AST(抽象樹)。添加自己的代碼。

實戰

如何自己實現一個自動添加Setter/Getter的工具?

首先,我們創建一個自己的注解。

@Retention(RetentionPolicy.SOURCE) // 注解只在源碼中保留
@Target(ElementType.TYPE) // 用于修飾類
public @interface MySetterGetter {
}

創建一個需要生成setter/getter方法的實體類

@MySetterGetter  // 打上我們的注解
public class Test {
private String wzj;
}

接下來就來看一看如何來生成我們想要的字符串。

整體代碼如下:

@SupportedAnnotationTypes("com.study.practice.nameChecker.MySetterGetter")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MySetterGetterProcessor extends AbstractProcessor {
// 主要是輸出信息
private Messager messager;
private JavacTrees javacTrees;

private TreeMaker treeMaker;
private Names names;
@Override
public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv);
this.messager = processingEnv.getMessager();
this.javacTrees = JavacTrees.instance(processingEnv);
Context context = ((JavacProcessingEnvironment)processingEnv).getContext();
this.treeMaker = TreeMaker.instance(context);
this.names = Names.instance(context);
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
// 拿到被注解標注的所有的類
Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(MySetterGetter.class);
elementsAnnotatedWith.forEach(element -> {
// 得到類的抽象樹結構
JCTree tree = javacTrees.getTree(element);
// 遍歷類,對類進行修改
tree.accept(new TreeTranslator(){
@Override
public void visitClassDef(JCTree.JCClassDecl jcClassDecl){
List<JCTree.JCVariableDecl> jcVariableDeclList = List.nil();
// 在抽象樹中找出所有的變量
for(JCTree jcTree: jcClassDecl.defs){
if (jcTree.getKind().equals(Tree.Kind.VARIABLE)){
JCTree.JCVariableDecl jcVariableDecl = (JCTree.JCVariableDecl)jcTree;
jcVariableDeclList = jcVariableDeclList.append(jcVariableDecl);
}
}

// 對于變量進行生成方法的操作
for (JCTree.JCVariableDecl jcVariableDecl : jcVariableDeclList) {
messager.printMessage(Diagnostic.Kind.NOTE, jcVariableDecl.getName() + " has been processed");
jcClassDecl.defs = jcClassDecl.defs.prepend(makeSetterMethodDecl(jcVariableDecl));

jcClassDecl.defs = jcClassDecl.defs.prepend(makeGetterMethodDecl(jcVariableDecl));
}


// 生成返回對象
JCTree.JCExpression methodType = treeMaker.Type(new Type.JCVoidType());

return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC), getNewSetterMethodName(jcVariableDecl.getName()), methodType, List.nil(), parameters, List.nil(), block, null);
}
/**
* 生成 getter 方法
* @param jcVariableDecl
* @return
private JCTree.JCMethodDecl makeGetterMethodDecl(JCTree.JCVariableDecl jcVariableDecl){
ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>();
// 生成表達式
JCTree.JCReturn aReturn = treeMaker.Return(treeMaker.Ident(jcVariableDecl.getName()));
statements.append(aReturn);
JCTree.JCBlock block = treeMaker.Block(0, statements.toList());
// 無入參
// 生成返回對象
JCTree.JCExpression returnType = treeMaker.Type(jcVariableDecl.getType().type);
return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC), getNewGetterMethodName(jcVariableDecl.getName()), returnType, List.nil(), List.nil(), List.nil(), block, null);
}
/**
* 拼裝Setter方法名稱字符串
* @param name
* @return
private Name getNewSetterMethodName(Name name){
String s = name.toString();
return names.fromString("set" + s.substring(0,1).toUpperCase() + s.substring(1, name.length()));
}
/**
* 拼裝 Getter 方法名稱的字符串
* @param name
* @return
private Name getNewGetterMethodName(Name name){
String s = name.toString();
return names.fromString("get" + s.substring(0,1).toUpperCase() + s.substring(1, name.length()));
}
/**
* 生成表達式
* @param lhs
* @param rhs
* @return
private JCTree.JCExpressionStatement makeAssignment(JCTree.JCExpression lhs, JCTree.JCExpression rhs){
return treeMaker.Exec(
treeMaker.Assign(lhs, rhs)
);
}
}

代碼有點多,我們逐一拆解說明:

下面這是整個代碼結構的腦圖,后面的講解會基于這個順序。

a. 注解

@SupportedAnnotationTypes 表示我們需要監聽的注解,比如我們之前定義的 @MySetterGetter。

@SupportedSourceVersion 表示我們想要對什么版本的Java源代碼進行處理。?

b. 父類

AbstractProcessor是本次的核心類,編譯器在編譯的時候會掃描此類的子類。其中有一個子類必須實現的核心方法 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv),此方法如果是返回為true就說明編譯的那個類抽象樹的結構又變化,需要重新進行詞法分析和語法分析(可以查看上面提到的那個編譯流程圖)。如果返回的是false就說明沒有變化。

c. process方法

主要的操作邏輯是:

1、拿到所有被我們MySetterGetter標注的類。

2、遍歷所有的類,生成類的抽象樹結構。

3、對類進行操作:

a.找到類中所有的變量。

b.對變量進行生成Set和Get方法。

4、返回 true,說明類結構變了,需要重新解析。如果是false說明沒有變,不用重新解析。?

d. 操作JCTree樹

主要是在操作抽象樹,可以查看文末附件中的文章進行學習。

?e. 方法名稱拼接

這一塊兒和字符串拼接沒啥區別,用過反射的同學應該也都清楚這個操作了。?

到此為止,我們就已經介紹完了Lombok的原理。怎么樣是不是很簡單。接下來,就讓我們把它運行起來,投入到實戰之中。?

f. 運行

最后來看一下如何正確的運行這個我們寫的工具。

1.環境

我的系統環境是 macOs Monterey;

java版本是

openjdk version "1.8.0_302"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed mode)

2.編譯processor

?在你存放 MySetterGetter 和 MySetterGetterProcessor 兩個類的目錄下進行編譯。

javac -cp $JAVA_HOME/lib/tools.jar MySetterGetter.java MySetterGetterProcessor.java

執行成功后會出現這三個class文件。

3.聲明插入式注解處理器

  • 在你的工程的resources下面創建一個包,名稱為:META-INFO.services
  • 然后創建一個文件,名稱為:javax.annotation.processing.Processor
  • 將你的注解處理器的地址填入,我的配置是這樣的:

com.study.practice.nameChecker.MySetterGetterProcessor

4.用我們的工具去編譯目標類

比如我們本次是要編譯那個test.java。

它的內容再回顧一下:

@MySetterGetter  // 打上我們的注解
public class Test {
private String wzj;
}

然后我們就去編譯它(注意類前面的路徑。這個你們得換成自己的工程目錄。)

javac -processor com.study.practice.nameChecker.MySetterGetterProcessor com/study/practice/nameChecker/Test.java

執行之后如果沒有修改我的代碼的話會打印這幾個字符串:

process 1
process 2
: wzj has been processed
process 1

最后會生成Test.class文件。

5.成果

最后的class文件解析出來就是這個樣子的。如下圖所示:

看到Setter/Getter方法就說明我們已經大功告成了!是不是很簡單。

到此為止,我們就學會了如何自己寫一個屬于自己的簡易Lombok的插件了。

附件

treemarker 的介紹:

http://www.docjar.com/docs/api/com/sun/tools/javac/tree/TreeMaker.html

責任編輯:張燕妮 來源: 阿里云云棲號
相關推薦

2022-08-11 17:14:37

Java

2022-06-27 07:32:00

JavaArrayList語法糖

2018-05-20 11:01:47

Siri語音助手手機

2021-07-21 10:10:14

require前端代碼

2021-11-08 10:00:19

require前端模塊

2019-12-18 15:11:42

數組集合數據

2019-11-27 10:54:43

Tomcat連接數線程池

2024-08-02 16:31:12

2021-02-18 16:06:43

JavaStream代碼

2018-08-20 20:46:07

2017-12-19 11:54:51

微信朋友圈同步

2018-01-31 10:24:45

熱插拔原理服務器

2020-12-07 11:05:21

HttpClient代碼Java

2022-02-08 13:39:35

LinuxUNIX系統

2025-03-25 10:49:13

2020-06-03 08:15:50

IO軟件

2022-01-25 12:41:31

ChromeResponse接口

2023-01-13 16:53:17

Annotation底層元注解

2020-02-15 15:33:55

Python如何運作

2010-01-06 15:36:30

Linux操作系統
點贊
收藏

51CTO技術棧公眾號

精品无人国产偷自产在线| 亚洲综合999| 国产啪精品视频| 性欧美videos| 日本精品影院| 欧美日韩国产色站一区二区三区| 成人性做爰片免费视频| 欧美视频久久久| 免费国产亚洲视频| 久久久久久国产免费| 国产成人一区二区在线观看| 免费看日产一区二区三区| 精品久久久香蕉免费精品视频| 午夜精品一区二区在线观看| 成人毛片在线免费观看| 蜜桃久久av一区| 97视频在线观看播放| 99国产精品无码| 欧美18免费视频| 日韩一级二级三级| 日韩无套无码精品| 成人免费网站观看| 亚洲精品免费视频| 中文字幕日韩精品久久| 国内精品一区视频| 99综合电影在线视频| 亚洲伊人久久大香线蕉av| 无码人妻精品一区二区三区蜜桃91 | 午夜久久久影院| 伊人久久青草| 高清在线观看av| av成人免费在线观看| 91中文精品字幕在线视频| 看黄色一级大片| 国产精品毛片在线| 国内外成人免费激情在线视频网站 | 91精品国产自产91精品| 精品国产乱码久久久久久鸭王1| 欧美限制电影| 亚洲午夜av久久乱码| aaaaa一级片| 欧美91在线| 亚洲精品国产精品自产a区红杏吧| 国产精品19p| 欧美2区3区4区| 91麻豆精品国产91久久久| 国产精品区在线| 激情久久一区二区| 欧美日韩不卡一区| 在线免费黄色网| 97久久中文字幕| 6080午夜不卡| 亚洲一二三区av| 欧美日韩在线精品一区二区三区激情综合 | 日韩精品社区| 亚洲欧洲在线视频| 亚洲国产日韩一区无码精品久久久| 亚洲小说图片视频| 亚洲人成电影网| 日本欧美一区二区三区不卡视频| 成人三级视频| 日韩网站免费观看高清| 少妇人妻丰满做爰xxx| 久久精品青草| 欧美极品少妇xxxxⅹ裸体艺术| 久久99久久久| 99热这里只有精品8| 欧洲亚洲免费在线| 日本精品入口免费视频| 久久国产精品99久久人人澡| 成人女保姆的销魂服务| 国产丝袜在线视频| caoporn国产精品| 欧美日韩一区二| 在线播放日本| 亚洲综合av网| 成人小视频在线看| 久久青草视频| 精品少妇一区二区三区免费观看| 少妇一级淫片免费放播放| 亚洲综合小说图片| 爱福利视频一区| 青娱乐免费在线视频| 国产偷自视频区视频一区二区| 日本免费久久高清视频| 一级片免费观看视频| 国产美女在线观看一区| 国产视频一区二区不卡| 久久天堂电影| 亚洲精品网站在线观看| 国产美女无遮挡网站| 福利一区二区三区视频在线观看| 欧美一区二区观看视频| 久久中文字幕人妻| 在线中文字幕第一区| 5252色成人免费视频| 国产原创中文av| 99久久99久久精品免费看蜜桃| 日韩欧美一区二区三区四区 | 亚洲一区在线电影| 在线观看免费成人av| 福利欧美精品在线| 日韩在线观看网站| 国产精品乱子伦| 国产不卡高清在线观看视频| 欧美日韩卡一卡二| 翡翠波斯猫1977年美国| 亚洲欧美日韩成人在线| 中文一区二区在线观看| 成人在线免费观看视频网站| 浪潮色综合久久天堂| 日韩美女在线视频| 超碰人人干人人| 国产精品久久国产愉拍| 91网站在线看| а√天堂中文在线资源bt在线| 毛片在线能看| 国产欧美日韩视频一区二区| 9191国产视频| 欧美激情三区| 国产视频精品自拍| 久久影院一区二区| 精品一区二区精品| 日韩亚洲一区在线播放| av资源一区| 91麻豆精品国产91久久久资源速度| 日本黄色片在线播放| 欧美日韩一区二区高清| 91精品国产自产在线| 国产一级片在线| 午夜精品久久久久久久蜜桃app| 97人人爽人人| 久久国产精品亚洲人一区二区三区 | 亚洲自拍欧美另类| 日本黄色片在线观看| 色88888久久久久久影院野外| 久久久午夜精品福利内容| 久久久久电影| 国产日韩在线视频| 91视频在线观看| 欧美日韩综合在线免费观看| 丰满圆润老女人hd| 久久久久国产一区二区| 久久99精品久久久久久秒播放器| 国产三线在线| 亚洲精品在线观| 日韩手机在线观看| 狠狠色2019综合网| 亚洲第一视频网| www.99re7| 国内精品伊人久久久久av一坑| 日韩中文一区二区三区| 欧美一区 二区 三区| 亚洲精品福利在线观看| 日韩免费一二三区| 成年人国产精品| 欧美成人一区二区在线观看| 乱中年女人伦av一区二区| 久久久噜噜噜久久久| 欧美一区二区三区黄片| 黄网动漫久久久| 国产全是老熟女太爽了| 秋霞国产午夜精品免费视频| 国产精品素人一区二区| 精品国产免费av| 中文字幕在线1| 国产女优一区| 欧美一卡2卡3卡4卡无卡免费观看水多多| 午夜影院在线播放| 一区二区三区视频在线| 在线观看免费高清视频| 亚洲色图视频免费播放| www.四虎精品| 国产偷自视频区视频一区二区| 欧美日韩三区四区| 亚洲伦理网站| 97精品视频在线观看| 九色在线免费| 69堂国产成人免费视频| 国产一级aa大片毛片| av在线综合网| 午夜国产一区二区三区| 亚洲乱码中文字幕综合| 美女日批免费视频| 精品一区在线| 成人黄色午夜影院| 第一av在线| 亚洲最大中文字幕| www国产一区| 色综合天天综合网天天狠天天| 国产无遮挡在线观看| 国产成人免费高清| 精品视频无码一区二区三区| 午夜国产一区二区| 国产伦精品一区二区三毛| 午夜无码国产理论在线| 两个人的视频www国产精品| 天天操天天干天天爽| 欧美日韩精品一区二区在线播放| 国产精品7777777| 国产精品久久久久四虎| 好男人香蕉影院| 九九九久久久精品| 成人一级片网站| 欧美日韩国产成人精品| 色噜噜一区二区| 黄色美女久久久| 91久久精品美女高潮| 中文字幕一区久| 久久久久久国产精品三级玉女聊斋 | 欧美日本不卡视频| 91av在线免费视频| 亚洲综合一二区| 91香蕉视频在线播放| 久久精品男人天堂av| 国产乱淫av片| 国产一区二区久久| 亚洲另类第一页| 久久精品一区二区三区中文字幕| 99久久久精品视频| 91成人网在线观看| 亚洲精品二区| 九九视频精品全部免费播放| 国产欧美一区二区视频| 欧美视频二区欧美影视| 国产免费一区视频观看免费 | 97se在线视频| 自拍偷拍亚洲| 国产精品视频播放| 在线日本欧美| 国产精品高潮呻吟久久av无限 | 国产在线一区二区三区| se01亚洲视频| 国产成人一区二区三区| 亚洲天堂资源| 国产福利精品av综合导导航| 涩涩网在线视频| 欧美在线免费观看| 亚洲女同志freevdieo| 91国在线精品国内播放| 91桃色在线| 91chinesevideo永久地址| 国内小视频在线看| 久久久亚洲国产| 岛国av免费在线观看| 欧美精品九九久久| 理论片午夜视频在线观看| 国内精品久久久久久久久| 女人天堂av在线播放| 欧美激情视频在线| 超碰在线视屏| 日韩av不卡电影| 亚洲成人va| 成人激情在线播放| 奇米一区二区| 一本色道久久综合亚洲精品不| 玛丽玛丽电影原版免费观看1977| 色婷婷久久久| 日韩精品久久久毛片一区二区| 禁断一区二区三区在线| 欧美午夜免费电影| 日韩精品视频网址| 韩国理伦片一区二区三区在线播放| 午夜久久久精品| 国产一区二区在线电影| 波多野结衣电影免费观看| 国产精品1区二区.| 亚洲国产精品狼友在线观看| 成人免费毛片嘿嘿连载视频| 久久久久无码国产精品一区李宗瑞| 成人激情校园春色| 特大黑人巨人吊xxxx| 久久久精品中文字幕麻豆发布| 亚洲黄色免费视频| 亚洲免费看黄网站| 日产欧产va高清| 欧美亚洲动漫制服丝袜| 一级黄色片在线| 亚洲第一福利在线观看| 免费在线黄色网址| 久久久91精品| 欧美13videosex性极品| 国产日韩中文字幕| 精品淫伦v久久水蜜桃| 日韩伦理一区二区三区av在线| 91精品福利| 国内性生活视频| 国精产品一区一区三区mba桃花| 91人妻一区二区| 国产日韩欧美不卡在线| 国产精品三区在线观看| 婷婷综合在线观看| 国产又粗又黄又爽| 亚洲国内精品视频| 永久av在线| 51久久精品夜色国产麻豆| av一级久久| 欧美视频观看一区| 影音先锋中文字幕一区| 久久久久久蜜桃一区二区| 成人综合婷婷国产精品久久蜜臀| 亚洲ⅴ国产v天堂a无码二区| 夜夜操天天操亚洲| 中文字幕第2页| 精品亚洲va在线va天堂资源站| 免费网站黄在线观看| 2019av中文字幕| 亚洲**毛片| 亚洲成年人专区| 日本一区中文字幕| 少妇精品一区二区| 亚洲最新视频在线观看| 91禁在线观看| 国产亚洲精品久久久久久牛牛| 美女视频在线免费| 国产成人av一区二区三区| 亚洲成av人片一区二区密柚| 日韩精品无码一区二区三区免费| 粉嫩一区二区三区性色av| 欧美美女性生活视频| 在线视频国产一区| 神马电影在线观看| 亚洲3p在线观看| av成人app永久免费| 狠狠干视频网站| 精品在线视频一区| 网站永久看片免费| 欧美三级电影精品| yiren22亚洲综合伊人22| 欧美亚洲另类制服自拍| 蜜桃久久久久| 国产精品久久久久7777| 国产精品12区| 免费无遮挡无码永久在线观看视频 | 国产亚洲精品美女久久久| 毛片电影在线| 国内精品视频在线播放| 亚洲精品影视| 国产 中文 字幕 日韩 在线| 亚洲国产综合视频在线观看| 亚洲第一天堂影院| 欧美精品videosex极品1| 日韩一二三区在线观看| 国内精品国产三级国产99| 国产一区二区三区久久久| 国产精品嫩草影院俄罗斯| 综合在线影院| 国产伦精品一区二区三区照片91| 欧美激情1区| 久久久高清视频| 午夜亚洲国产au精品一区二区| 日本黄色免费视频| 午夜精品在线视频| 校花撩起jk露出白色内裤国产精品| 无码播放一区二区三区| 久久综合久久综合九色| 岛国av中文字幕| 伊人精品在线观看| 亚洲老司机网| 久久av资源网站| 国产一区二区三区视频免费观看| 色阁综合伊人av| 成人豆花视频| 欧美久久久久久久久久久久久久| 成人aa视频在线观看| 日韩免费视频一区二区视频在线观看| 亚洲欧美日韩成人| 免费成人高清在线视频| 青青草原网站在线观看| 懂色av一区二区夜夜嗨| 五月婷婷中文字幕| 中文字幕亚洲精品| 超碰精品在线观看| 免费av网址在线| 亚洲欧洲一区二区在线播放| 国产激情视频在线播放| 91国产在线精品| 日韩中文首页| 日本性生活一级片| 91黄色免费版| 久久手机免费观看| 51国偷自产一区二区三区| 一本色道久久综合一区| 色www亚洲国产阿娇yao| 精品三级av在线| 欧美三区四区| 国产情侣第一页| 欧美激情一二三区| 亚洲精品久久久蜜桃动漫| 国产v综合ⅴ日韩v欧美大片| 91久久电影| 在线不卡av电影| 欧美一级艳片视频免费观看| 理论片午夜视频在线观看| 在线国产精品网| 26uuu欧美| www.av网站| 国产精品视频内| 国产精品毛片一区二区三区| 一区二区三区四区五区|