精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美成人一区二区三区高清| 日韩欧美精品免费| 伊人成年综合网| 麻豆一区二区麻豆免费观看| 精品美女久久久久久免费| 国产一区自拍视频| 男人天堂av在线播放| 国产精品丝袜在线播放| 午夜精品一区二区三区电影天堂| 精品一区二区久久久久久久网站| 久久久精品视频免费| 亚洲第一福利社区| 欧美日韩亚洲另类| 粉嫩av一区二区三区天美传媒| aa视频在线免费观看| 亚洲精品孕妇| 一区二区三区久久精品| 加勒比av中文字幕| 91九色在线播放| 欧美国产日韩亚洲一区| 国产精品入口麻豆九色| 国产精品福利网站| 来吧亚洲综合网| 91成人午夜| 色综合久久综合网97色综合| 一区二区不卡在线观看| 丰满肉嫩西川结衣av| 日韩精品欧美精品| 欧美夫妻性视频| 日韩一级av毛片| 一区二区三区四区精品视频 | 免费在线成人av| 亚洲熟妇无码久久精品| 亚洲欧洲综合| 久久久国产成人精品| 欧美日韩一区二区区| 亚洲va中文在线播放免费| 亚洲乱码中文字幕| 另类视频在线观看+1080p| 国产视频aaa| 日韩激情视频网站| 久久91精品国产91久久久| 永久免费毛片在线观看| 7m精品国产导航在线| 欧美日韩一区二区三区免费看| 北条麻妃在线视频观看| 91高清在线观看视频| 国产欧美一区二区三区在线看蜜臀| 高清视频一区二区三区| 国产又粗又猛又爽又黄的| 午夜亚洲影视| 久久久久久国产免费| 久草福利资源在线| av亚洲免费| 亚洲成人精品视频| 色男人天堂av| 国外成人福利视频| 日本电影亚洲天堂一区| 国产二区视频在线| 91在线中文| 亚洲女女做受ⅹxx高潮| 日韩精品电影网站| 韩国三级av在线免费观看| av成人动漫在线观看| 国产精品一区二区三区在线| 亚洲精品国偷拍自产在线观看蜜桃| 麻豆国产欧美一区二区三区| 国产精品扒开腿做爽爽爽男男| 日本黄色片视频| 国产精品mm| 欧美黑人极品猛少妇色xxxxx| 精品无码一区二区三区蜜臀| 99精品视频在线| 日韩在线中文字| 成人无码精品1区2区3区免费看| 欧美色网址大全| 亚洲性无码av在线| 亚洲中文字幕无码av| 日韩欧美一级| 欧美成人vr18sexvr| 在线播放av网址| 北条麻妃一区二区三区在线观看| 精品久久久久一区二区国产| 免费啪视频在线观看| 国产精品tv| 亚洲国产美女久久久久| 国产又粗又猛又色| 性人久久久久| 在线成人激情视频| 四虎精品免费视频| 欧美丰满日韩| 蜜臀久久99精品久久久无需会员| 久久久www成人免费毛片| 亚洲精品中文字幕乱码| 九九热在线精品视频| 日韩成人av毛片| 国产精品一区亚洲| 国产精品久久久久久久久久尿| 国产精品无码一区| 韩国午夜理伦三级不卡影院| 超碰97在线人人| 天天操天天干天天操| 久久欧美一区二区| 影音先锋亚洲视频| 成人短视频在线| 亚洲国产裸拍裸体视频在线观看乱了 | 看片网站在线观看| 99国产精品久久久久久久成人热 | 手机av在线| 欧美网站大全在线观看| 黑人无套内谢中国美女| 爽爽窝窝午夜精品一区二区| 中文字幕亚洲一区二区三区| 免费成人深夜夜行网站| 99精品视频免费观看| 国产精品三级久久久久久电影| 国产成人精品一区二三区四区五区 | 亚洲精品中文字幕在线| 伊人在我在线看导航| 精品久久久久久久久久久久久| 久久成人免费观看| a成人v在线| 亚洲成人aaa| 国产精品1区2区3区4区| 亚洲日本国产| 国产日韩换脸av一区在线观看| 日韩性xxxx| 久久精品夜色噜噜亚洲aⅴ| 国产精品一区在线免费观看| 一呦二呦三呦精品国产| 精品久久久久久最新网址| 日本一道本视频| 1000部精品久久久久久久久| 国产日韩欧美夫妻视频在线观看| 视频一区二区三区在线看免费看| 中文字幕日韩av资源站| 日韩欧美xxxx| 麻豆成人入口| 欧美激情xxxx| 国产又粗又猛视频免费| 久久蜜桃香蕉精品一区二区三区| 国产乱子伦精品视频| 日本免费成人| 亚洲欧美福利视频| 国产无套粉嫩白浆内谢| 国产在线精品免费av| 无码免费一区二区三区免费播放| 2019中文字幕在线电影免费| 欧美一区二区久久| 一级黄色片网址| 久久久精品五月天| 精品亚洲第一| av在线网页| 欧美草草影院在线视频| 91免费公开视频| 日韩精品一区第一页| 成人看片视频| 麻豆福利在线观看| 717成人午夜免费福利电影| 舐め犯し波多野结衣在线观看| 激情文学一区| 国产精品一区二区av| 超碰在线免费播放| 欧美日韩免费视频| 毛片久久久久久| 人人狠狠综合久久亚洲| 日本10禁啪啪无遮挡免费一区二区| 亚洲欧美小说色综合小说一区| 亚洲欧美成人网| 亚洲网站免费观看| 亚洲美女屁股眼交| 菠萝菠萝蜜网站| 免费国产亚洲视频| 日韩一二区视频| 日韩极品少妇| 国产精品三级在线| 成人影音在线| 亚洲欧美日韩精品久久| 一级片aaaa| 亚洲一区二区三区三| 性久久久久久久久久| 日本美女一区二区三区| 国产一级大片免费看| 亚洲视频分类| 91网站免费观看| 黄视频网站在线观看| 亚洲视频网站在线观看| 国产免费不卡视频| 黑人与娇小精品av专区| 天堂网av2018| 91亚洲精品乱码久久久久久蜜桃| 免费看污污网站| 亚洲激情视频| 一区二区精品国产| 国产图片一区| 国产欧美日韩高清| 九色porny自拍视频在线播放| 最新日韩中文字幕| 偷拍精品一区二区三区| 欧美欧美欧美欧美| 中文字幕视频网| 一区二区三区在线免费视频| 中文字幕网站在线观看| 国产 日韩 欧美大片| 黄色在线视频网| 亚洲精品护士| 成人毛片100部免费看| 精品国产日韩欧美| 国产视频一区二区不卡| 国产一区二区久久久久| 国产精品吊钟奶在线| 国产福利电影在线播放| 久久亚洲影音av资源网| 第九色区av在线| 国产视频精品在线| 亚洲黄色一级大片| 91麻豆精品国产91久久久使用方法 | 激情高潮到大叫狂喷水| 久久日韩粉嫩一区二区三区| 蜜臀视频在线观看| 国产在线视频一区二区三区| 日本老熟妇毛茸茸| 亚洲一区自拍| 亚洲美免无码中文字幕在线 | 亚洲国产成人一区二区| 欧美日韩久久久久久| 日韩三级一区二区| 天天综合日日夜夜精品| 久艹视频在线观看| 综合欧美一区二区三区| 国产又粗又猛又爽又黄的视频四季 | 欧美精品日韩精品| 中国一级特黄视频| 日本黄色一区二区| 日日噜噜噜噜人人爽亚洲精品| 亚洲成a人片在线观看中文| 久草免费新视频| 一区二区高清免费观看影视大全 | 欧美三级电影在线观看| 国产熟妇一区二区三区四区| 欧美视频一区二区三区…| 国产在线观看免费视频今夜| 亚洲精品国产第一综合99久久| 裸体武打性艳史| 亚洲欧美日韩国产综合| 日韩精品一区二区亚洲av性色 | 五月天综合激情| 亚洲成av人片在www色猫咪| 免费一级a毛片夜夜看| 一区二区三区在线观看动漫| 久久综合色综合| 亚洲电影一区二区三区| 天堂网一区二区三区| 欧美日韩亚洲高清| 超碰超碰超碰超碰| 色综合久久久久| 中文天堂在线播放| 欧美巨大另类极品videosbest| 亚洲网站免费观看| 日韩欧美亚洲一区二区| 国产 欧美 自拍| 精品亚洲va在线va天堂资源站| 伦理片一区二区三区| 尤物yw午夜国产精品视频明星| 尤物网在线观看| 久久国产精品99国产精| 成人超碰在线| 欧美最近摘花xxxx摘花| 日本综合视频| 91情侣偷在线精品国产| h视频久久久| 欧美日韩高清在线一区| 久久蜜桃av| 福利在线一区二区| 快she精品国产999| 欧美激情国内自拍| 波多野结衣91| 久久精品三级视频| 亚洲精品日韩一| 国产综合精品视频| 91精品国产综合久久香蕉麻豆 | 亚洲欧美中文日韩在线| 在线观看麻豆| 午夜精品www| 国产在视频一区二区三区吞精| 99久久国产免费免费| 深爱激情综合网| 麻豆一区二区三区在线观看| 一本色道久久综合亚洲精品不卡| 最近中文字幕一区二区| 丁香婷婷综合色啪| 91狠狠综合久久久久久| 亚洲成人综合在线| 最近中文字幕在线视频| 精品第一国产综合精品aⅴ| 第九色区av在线| 久久久久久久91| 嫩草伊人久久精品少妇av杨幂| 1卡2卡3卡精品视频| 狠狠做深爱婷婷综合一区| 大伊香蕉精品视频在线| 久久精品国内一区二区三区 | 国产精品乱人伦| 久久不卡免费视频| 欧美一区二区福利在线| 国产午夜视频在线观看| 久久999免费视频| 日本黄色成人| 日本精品一区二区| 一区在线免费| 亚洲一二区在线观看| 国产拍揄自揄精品视频麻豆| 国产成人亚洲欧洲在线| 欧美一区二区三区公司| 高清性色生活片在线观看| 国语自产精品视频在线看一大j8| 99精品在线免费观看| 日日噜噜噜噜夜夜爽亚洲精品| 99精品国产在热久久| 黑人巨大猛交丰满少妇| 国产精品视频在线看| 国产性生活视频| 亚洲国产中文字幕久久网 | 57pao精品| 加勒比色老久久爱综合网| 老司机午夜网站| 久久99国产精品尤物| 成人小视频免费看| 日本韩国一区二区| 青青草视频在线免费观看| 69久久夜色精品国产7777| 99精品国产一区二区三区2021| 手机在线视频你懂的| 久久99精品久久久久久久久久久久 | 日韩成人午夜| 国精产品一区一区三区视频| 成人综合婷婷国产精品久久免费| 91视频综合网| 日韩一区二区在线看| free性欧美hd另类精品| 91免费看国产| 中文字幕亚洲精品乱码| 91免费视频污| 亚洲免费av观看| 国产夫绿帽单男3p精品视频| 欧美精品日韩www.p站| 秋霞影院一区| 人妻激情另类乱人伦人妻| 国产成人精品综合在线观看 | 色94色欧美sute亚洲线路一久 | 日韩视频免费在线播放| 久久一区二区三区四区| 国产一级免费视频| 亚洲男人天堂九九视频| 黑人巨大精品| 亚洲成人自拍视频| 国内一区二区视频| 国模无码国产精品视频| 精品免费国产二区三区| 岛国在线视频网站| 欧美一区二区三区成人久久片| 日本亚洲三级在线| 国产午夜手机精彩视频| 精品福利视频一区二区三区| 午夜av不卡| 亚洲精品一区二区三区蜜桃久| 国产在线精品国自产拍免费| 久久久久亚洲av成人片| 日韩精品在线第一页| 成人影院在线免费观看| 中文字幕色呦呦| 26uuu精品一区二区| 国产成人精品一区二区色戒| 久久精品国产亚洲一区二区| 成人线上播放| 欧美日韩在线成人| 亚洲欧美视频一区| 五月婷婷六月色| 国产精品一区二区三区免费视频 | 精品无人乱码| 成人黄色av网| 99视频精品| 在线视频这里只有精品| 精品免费99久久| 日本一区二区电影| 日韩成人手机在线| 国产日韩在线不卡| 国产成人免费看一级大黄| 欧美有码在线观看| 91精品一区国产高清在线gif| 国产美女视频免费观看下载软件| 欧美艳星brazzers| 欧美xxxx免费虐| 视频在线观看成人| 丰满白嫩尤物一区二区| 性高潮视频在线观看| 欧美精品九九久久| 全球成人免费直播| www.日本高清| 日韩欧美国产不卡|