一、lombok原理 JSR269
什么是JSR ?
JSR是Java Specification Requests的縮寫,意思是Java 規(guī)范提案。是指向JCP(Java Community Process)提出新增一個(gè)標(biāo)準(zhǔn)化技術(shù)規(guī)范的正式請(qǐng)求。任何人都可以提交JSR,以向Java平臺(tái)增添新的API和服務(wù)。
有超過(guò)300的JSR。一些更為明顯的JSRs包括:
的JSR# | 規(guī)格或技術(shù) |
---|---|
1 | 實(shí)時(shí)規(guī)范為Java(RTSJ規(guī)范)1.0 |
3 | Java管理擴(kuò)展(JMX)的1.0,1.1和1.2 [ 2 ] |
5 | Java API的XML處理(JAXP)1.0 |
8 | OSGI的開放服務(wù)網(wǎng)關(guān)規(guī)范 |
9 | 次郎(聯(lián)邦管理體系規(guī)范)1.0 |
12 | Java數(shù)據(jù)對(duì)象(JDO的)1.0 |
13 | 改進(jìn)的BigDecimal(Java平臺(tái),標(biāo)準(zhǔn)版#java.math) |
14 | 加入到Java編程語(yǔ)言(如J2SE 5.0的泛型類型) |
16 | Java EE連接器架構(gòu)(JCA)的1.0 |
19 | 企業(yè)JavaBeans(EJB)2.0 |
22 | JAIN SLEE API規(guī)范(JSLEE)的1.0 |
30 | 連接有限設(shè)備配置(CLDC)1.0 的Java ME |
31 | 用于XML綁定的Java體系結(jié)構(gòu)(JAXB)的1.0 |
32 | JAIN SIP API規(guī)范(JSIP)的1.0,1.1和1.2的Java ME |
36 | 連接設(shè)備配置(CDC)的1.0為Java ME |
37 | 移動(dòng)信息設(shè)備描述(MIDP)1.0為Java ME |
40 | Java元數(shù)據(jù)接口(JMI)1.0 |
41 | 一個(gè)簡(jiǎn)單的斷言基金(J2SE 1.4中) |
47 | 日志 API規(guī)范(J2SE 1.4中) |
48 | WBEM服務(wù)規(guī)范(J2SE 1.4中) |
51 | 新的I / O API的Java平臺(tái)(J2SE 1.4的)(妞妞) |
52 | JavaServer Pages標(biāo)準(zhǔn)標(biāo)記庫(kù)(JSTL)的1.0和1.1 [ 3 ] |
53 | 的Java Servlet 2.3和JavaServer頁(yè)面(JSP)的1.2規(guī)格 |
54 | Java數(shù)據(jù)庫(kù)連接(JDBC)3.0 |
56 | Java網(wǎng)絡(luò)啟動(dòng)協(xié)議和API(JNLP的),1.0,1.5和6.0 [ 4 ](Java Web Start的) |
58 | Java 2平臺(tái)企業(yè)版(J2EE)的1.3 |
59 | Java 2平臺(tái)標(biāo)準(zhǔn)版(J2SE)的1.4(梅林) |
63 | 用于XML處理的Java API(JAXP)1.1和1.2 [ 5 ] |
68 | Java平臺(tái)Micro版(Java ME)的1.0 |
73 | Java數(shù)據(jù)挖掘 API(JDM)1.0 |
75 | J2ME平臺(tái)的PDA可選包 |
80 | 的Java 的USB API |
82 | 藍(lán)牙的Java API |
88 | Java EE的應(yīng)用程序部署 |
93 | 用于XML注冊(cè)的Java API(JAXR)1.0 |
94 | Java規(guī)則引擎API |
102 | Java的文檔對(duì)象模型(JDOM的)1.0 |
110 | Java API的WSDL(WSDL4J)1.0 |
112 | Java EE連接器架構(gòu)(JCA)的1.5 |
113 | 的Java Speech API的2(JSAPI2) |
114 | Java數(shù)據(jù)庫(kù)連接(JDBC)的RowSet實(shí)現(xiàn) |
116 | 的SIP Servlet API 1.0 |
118 | 移動(dòng)信息設(shè)備描述(MIDP)2.0為Java ME |
120 | 無(wú)線消息API(WMA)的 |
121 | 應(yīng)用程序隔離API |
127 | 的JavaServer Faces(JSF)的1.0和1.1 [ 6 ] |
133 | Java內(nèi)存模型和主題規(guī)范修訂 |
135 | Java ME的Java移動(dòng)媒體API(MMAPI)的 |
139 | 有限連接設(shè)備配置(CLDC)1.1為Java ME |
140 | 服務(wù)定位協(xié)議 “(SLP)的Java API |
141 | 會(huì)話描述協(xié)議(SDP)的API為Java |
151 | Java 2平臺(tái)企業(yè)版(J2EE)的1.4 |
152 | JavaServer頁(yè)面(JSP)的2.0 |
153 | 企業(yè)JavaBeans(EJB)2.1 |
154 | 的Java Servlet 2.4和2.5規(guī)格[ 7 ] |
160 | Java管理擴(kuò)展(JMX)的遠(yuǎn)程API 1.0 |
166 |
并發(fā)實(shí)用程序(J2SE 5.0中的java.util.concurrent ,java.util.concurrent.atomic 和java.util.concurrent.locks ) |
168 | Portlet規(guī)范 1.0 |
170 | 內(nèi)容庫(kù)的Java API(JCR)的1.0 |
172 | Java ME的Web服務(wù)規(guī)范 |
173 | 使用StAX(XML的流式API) |
175 | 一個(gè)Java編程語(yǔ)言的元數(shù)據(jù)工具 |
176 | Java 2平臺(tái)標(biāo)準(zhǔn)版(J2SE)的5.0(虎) |
177 | J2ME(SATSA的安全和信任服務(wù)API) |
179 | 位置API為Java ME 1.0 |
180 | 會(huì)話發(fā)起協(xié)議(SIP)API為Java ME |
181 | 用于Java平臺(tái)的Web服務(wù)元數(shù)據(jù) |
184 | 移動(dòng)3D圖形API為Java ME 1.0和1.1 |
185 | 無(wú)線行業(yè)Java技術(shù)(JTWI的) |
187 | 即時(shí)消息(的Java ME和Java SE中) |
198 | 一個(gè)標(biāo)準(zhǔn)擴(kuò)展API 的集成開發(fā)環(huán)境 |
199 | Java編譯器 API |
201 | 擴(kuò)展Java編程語(yǔ)言的枚舉,自動(dòng)裝箱,靜態(tài)導(dǎo)入循環(huán)和增強(qiáng)(J2SE 5.0的) |
202 | Java類文件規(guī)范更新 |
203 | 更多新的I / O API的Java平臺(tái)(NIO2) |
204 | Unicode增補(bǔ)字符支持(增加了J2SE 5.0的支持Unicode的 3.1) |
205 | 無(wú)線消息API 2.0 “(WMA)2.0 |
206 | 用于XML處理的Java API(JAXP)1.3 |
208 | Java業(yè)務(wù)集成(JBI)的1.0 |
215 | Java社區(qū)進(jìn)程(JCP)2.6 |
218 | 連接設(shè)備配置(CDC)的1.1為Java ME |
220 | 企業(yè)JavaBeans(EJB)3.0 |
221 | Java數(shù)據(jù)庫(kù)連接(JDBC)4.0 |
222 | 用于XML綁定(JAXB)的2.0 Java體系結(jié)構(gòu) |
223 | Java SE 6中Java平臺(tái)的腳本 |
224 | XML Web服務(wù)的Java API(JAX-WS的),繼承的JAX-RPC |
225 | 的XQuery API為Java(XQJ的) |
226 | 可調(diào)節(jié)2D矢量圖形 API 的Java ME |
229 | 支付API(PAPI的) |
231 | 針對(duì)OpenGL的Java綁定 |
234 | 高級(jí)多媒體補(bǔ)充 API為Java ME |
235 | 服務(wù)數(shù)據(jù)對(duì)象(SDO), |
239 | OpenGL ES的Java綁定 |
240 | JAIN SLEE API規(guī)范(JSLEE)的1.1 |
241 | Groovy編程語(yǔ)言 |
243 | Java數(shù)據(jù)對(duì)象(JDO的)2.0 |
244 | 的Java平臺(tái)企業(yè)版(Java EE)的5 |
880 | JavaServer頁(yè)面(JSP)的2.1 |
247 | Java數(shù)據(jù)挖掘 API(JDM)2.0 |
248 | 移動(dòng)服務(wù)架構(gòu) |
249 | 移動(dòng)服務(wù)架構(gòu)2 |
250 | 常見(jiàn)的注解的Java平臺(tái)(Java元數(shù)據(jù)設(shè)施) |
252 | 的JavaServer Faces(JSF)的1.2 |
253 | 移動(dòng)電話服務(wù)API(MTA), |
255 | Java管理擴(kuò)展(JMX)2.0 |
256 | 移動(dòng)傳感器API |
257 | 非接觸式通信API(NFC技術(shù)) |
260 | Javadoc的標(biāo)簽技術(shù)更新 |
269 | 可插拔注解處理API(Java元數(shù)據(jù)設(shè)施) |
270 | Java平臺(tái)標(biāo)準(zhǔn)版(Java SE)的6(野馬) |
271 | 移動(dòng)信息設(shè)備描述(MIDP)3.0為Java ME |
274 | BeanShell的腳本語(yǔ)言 |
275 | 單位規(guī)范(見(jiàn)計(jì)量單位) |
276 | 設(shè)計(jì)時(shí)元數(shù)據(jù)的的JavaServer面臨的組件 |
277 | Java模塊系統(tǒng) |
280 | 對(duì)于Java ME的XML API |
281 | IMS的服務(wù)API(見(jiàn)的IMS) |
282 | 為Java實(shí)時(shí)規(guī)范(RTSJ規(guī)范)1.1 |
283 | 內(nèi)容庫(kù)的Java API(JCR)的2.0 |
286 | Portlet規(guī)范 2.0 |
289 | 的SIP Servlet API 1.1 |
290 | Java語(yǔ)言與XML用戶界面標(biāo)記集成(XML用戶界面) |
291 | 針對(duì)Java SE動(dòng)態(tài)組件的支持(見(jiàn)的OSGi) |
292 | JavaTM平臺(tái)上支持動(dòng)態(tài)類型語(yǔ)言 |
293 | 位置API為Java ME 2.0 |
294 | 在Java編程語(yǔ)言的改進(jìn)模塊化支持 |
296 | Swing應(yīng)用程序框架(Java SE 7中) |
299 | Java的上下文和依賴注入(焊接) |
301 | JSF Portlet的橋梁 |
303 | Bean驗(yàn)證 |
307 | 移動(dòng)網(wǎng)絡(luò)和移動(dòng)數(shù)據(jù)API(截至7月正式計(jì)劃,20日,2007年,但官方發(fā)布2。問(wèn):2008 |
308 | 注解的Java類型(Java SE的8) |
311 | RESTful Web服務(wù)的Java API(JAX-RS的)1.0和1.1 |
314 | 的JavaServer Faces(JSF)的2.0 |
316 | 的Java平臺(tái)企業(yè)版(Java EE)的6 |
317 | Java持久性API(JPA)的2.0 |
322 | Java EE連接器架構(gòu)(JCA)的1.6 |
325 | IMS通信促成(ICE)的(見(jiàn)的IMS) |
330 | 對(duì)Java的依賴注入 |
343 | Java消息服務(wù) 2.0(JMS) |
354 | Java的貨幣及貨幣的API |
901 | Java語(yǔ)言規(guī)范,第三版(JLS的)(J2SE 5.0的集成的JSR 14,41,133,175,201和204) |
907 | Java事務(wù)API(JTA),1.0和1.1 |
912 | Java 3D的 API 1.3 |
913 | Java社區(qū)進(jìn)程(JCP)的2.0,2.1和2.5。[ 8 ] |
914 | Java消息服務(wù)(JMS)API的1.0和1.1 |
924 | 第二版(JVM)Java虛擬機(jī)規(guī)范(J2SE 5.0的)。[ 9 ] |
926 | 的Java 3D API 1.5 |
JSR269 可插拔的注解處理API,其原理如下:
二、實(shí)現(xiàn)步驟
1.工程與環(huán)境依賴
- 配置maven 插件,pom.xml 編譯參數(shù)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-parameters</arg>
<arg>-proc:none</arg>
<arg>-XDignore.symbol.file</arg>
</compilerArgs>
<compilerArguments>
<bootclasspath>
${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/../lib/tools.jar
</bootclasspath>
</compilerArguments>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
注意細(xì)節(jié)
- Lombok項(xiàng)目本身要加 編譯 參數(shù) ,防止編譯處理器無(wú)法實(shí)例化:-proc:none
- 要添加編譯 類路徑 bootclasspath: 指定tool.jar
- 在測(cè)試的時(shí)候 要構(gòu)建一個(gè)新的工程,用一個(gè)新的IDEA窗口打開
2.注解處理器
- 打印編譯信息
- 編寫注解處理器,實(shí)現(xiàn)
AbstractProcessor
- 基于SPI指定處理器的路徑 :工程/resources/META-INF/services/javax.annotation.processing.Processor
- 打印消息的時(shí)候,maven 用System.out, idea用
Messager
類 - 我當(dāng)時(shí)用ide 編譯時(shí)一直報(bào)錯(cuò) ,我沒(méi)太在意使用mvn 命令處理的, mvn命令沒(méi)錯(cuò)誤
Error:java: 服務(wù)配置文件不正確, 或構(gòu)造處理程序?qū)ο骿avax.annotation.processing.Processor: Provider com.wfg.HelloProcessor not found時(shí)拋出異常錯(cuò)誤
在項(xiàng)目編寫的目錄下操作下面的命令
mvn compile 編譯
mvn package 打包
mvn install 安裝到本地倉(cāng)庫(kù)
mvn exec:java -Dexec.mainClass="hello.HelloWorld" 運(yùn)行main類,此處用不到這個(gè)命令
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("com.wfg.MyHello")
public class HelloProcessor extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
System.out.println("這是我的第一人編譯注釋處理器");
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,"這是我的處理器");
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return false;
}
}
3.注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface MyHello {
}
4.jcTree 修改語(yǔ)法
- 構(gòu)建一個(gè)hello world 語(yǔ)句
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Names;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("org.myLombok.Hello")
public class HelloProcessor extends AbstractProcessor {
private JavacTrees javacTrees; // 獲取 JcTree
private TreeMaker treeMaker; // 構(gòu)建生成 jcTree
private Names names;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
System.out.println("這是我的第一人編譯注釋處理器");
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,"這是我的處理器");
javacTrees = JavacTrees.instance(processingEnv);// 語(yǔ)法樹
Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
this.treeMaker = TreeMaker.instance(context);
super.init(processingEnv);
this.names = Names.instance(context);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
annotations.stream()
.flatMap(t->roundEnv.getElementsAnnotatedWith(t).stream())
.forEach(t->{
JCTree tree = javacTrees.getTree(t);
// 基于訪問(wèn)者設(shè)計(jì)模式 去修改方法
tree.accept(new TreeTranslator(){
@Override
public void visitMethodDef(JCTree.JCMethodDecl tree) {
// System.out.println("hello world");
JCTree.JCStatement sysout = treeMaker.Exec(
treeMaker.Apply(
List.nil(),
select("System.out.println"),
List.of(treeMaker.Literal("hello world!")) // 方法中的內(nèi)容
)
);
// 覆蓋原有的語(yǔ)句塊
tree.body.stats=tree.body.stats.append(sysout);
super.visitMethodDef(tree);
}
});
});
return true;
}
private JCTree.JCFieldAccess select(JCTree.JCExpression selected, String expressive) {
return treeMaker.Select(selected, names.fromString(expressive));
}
private JCTree.JCFieldAccess select(String expressive) {
String[] exps = expressive.split("\\.");
JCTree.JCFieldAccess access = treeMaker.Select(ident(exps[0]), names.fromString(exps[1]));
int index = 2;
while (index < exps.length) {
access = treeMaker.Select(access, names.fromString(exps[index++]));
}
return access;
}
private JCTree.JCIdent ident(String name) {
return treeMaker.Ident(names.fromString(name));
}
}
4.新建模塊依賴我們這個(gè)jar包進(jìn)行編譯
/**
* @author wufagang
* @description
* @date 2023年04月18日 20:46
*/
@MyHello
public class HelloDemo {
}
編譯后到效果文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-422259.html
5.源碼調(diào)試
測(cè)試模塊引入下面的插件文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-422259.html
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
到了這里,關(guān)于手把手實(shí)現(xiàn)一個(gè)lombok的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!