lombok实现原理
大家在做java程序开发时会用到Lombok插件,在使用时大家都觉得其很方面,帮助我们消除Java代码的冗长,那么它的实现原理是什么呢?
在javac解析称抽象语法树之后,Lombok通过自己的注解解释器,动态修改语法树,插入新的节点到语法树中,最后通过分析生成字节码。
例如创建一个名为Getter的注解。
1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Target(ElementType.TYPE) 9 @Retention(RetentionPolicy.CLASS) 10 public @interface Getter { 11 }
为这个注解添加一个GetterProcessor解释器。JCTree、TreeMaker的相关用法见https://www.cnblogs.com/lwjblogs/p/15741065.html
1 import annotation.Getter; 2 import com.sun.source.tree.Tree; 3 import com.sun.tools.javac.api.JavacTrees; 4 import com.sun.tools.javac.code.Flags; 5 import com.sun.tools.javac.processing.JavacProcessingEnvironment; 6 import com.sun.tools.javac.tree.JCTree; 7 import com.sun.tools.javac.tree.TreeMaker; 8 import com.sun.tools.javac.tree.TreeTranslator; 9 import com.sun.tools.javac.util.*; 10 11 import javax.annotation.processing.*; 12 import javax.lang.model.SourceVersion; 13 import javax.lang.model.element.Element; 14 import javax.lang.model.element.TypeElement; 15 import javax.tools.Diagnostic; 16 import java.util.Set; 17 18 @SupportedSourceVersion(SourceVersion.RELEASE_8) 19 @SupportedAnnotationTypes("annotation.Getter") 20 public class GetterProcessor extends AbstractProcessor { 21 22 private Messager messager; 23 24 private TreeMaker treeMaker; 25 26 private JavacTrees trees; 27 28 private Names names; 29 @Override 30 public synchronized void init(ProcessingEnvironment processingEnv) { 31 super.init(processingEnv); 32 this.messager = processingEnv.getMessager(); 33 this.trees = JavacTrees.instance(processingEnv); 34 Context context =((JavacProcessingEnvironment) processingEnv).getContext(); 35 this.names = Names.instance(context); 36 this.treeMaker = TreeMaker.instance(context); 37 } 38 39 @Override 40 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 41 Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(Getter.class); 42 set.forEach(element->{ 43 JCTree jcTree = trees.getTree(element); 44 jcTree.accept(new TreeTranslator(){ 45 @Override 46 public void visitClassDef(JCTree.JCClassDecl jcClassDecl) { 47 List<JCTree.JCVariableDecl> jcVariableDecls = List.nil(); 48 for(JCTree jcTree : jcClassDecl.defs){ 49 if(jcTree.getKind().equals(Tree.Kind.VARIABLE)){ 50 JCTree.JCVariableDecl jcVariableDecl = (JCTree.JCVariableDecl) jcTree; 51 jcVariableDecls = jcVariableDecls.append(jcVariableDecl); 52 } 53 } 54 jcVariableDecls.forEach(jcVariableDecl -> { 55 messager.printMessage(Diagnostic.Kind.NOTE, jcVariableDecl.getName() + " has been processed"); 56 jcClassDecl.defs = jcClassDecl.defs.prepend(makeGetterDecl(jcVariableDecl)); 57 }); 58 super.visitClassDef(jcClassDecl); 59 } 60 }); 61 }); 62 return true; 63 } 64 65 private JCTree makeGetterDecl(JCTree.JCVariableDecl jcVariableDecl){ 66 ListBuffer<JCTree.JCStatement> listBuffer = new ListBuffer<>(); 67 listBuffer.add(treeMaker.Return(treeMaker.Select(treeMaker.Ident(names.fromString("this")),jcVariableDecl.getName()))); 68 JCTree.JCBlock block = treeMaker.Block(0,listBuffer.toList()); 69 return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC),getNewMethodName(jcVariableDecl.getName()) 70 ,jcVariableDecl.vartype, List.nil(), List.nil(), List.nil(),block,null); 71 } 72 73 private Name getNewMethodName(Name name) { 74 String s = name.toString(); 75 return names.fromString("get" + s.substring(0, 1).toUpperCase() + s.substring(1, name.length())); 76 } 77 }
创建一个名为Demo的测试样例。
import annotation.Getter; @Getter public class Demo{ private String test; private String value; }
使用javac编译Getter.java和GetterProcess.java成为Getter.class和GetterProcess.class
使用javac编译Demo.java javac -processor processor.GetterProcessor Demo.java 编译成功以后会生成一个Demo.class文件。
import annotation.Getter; @Getter public class Demo { private String test; private String value; public String getValue() { return this.value; } public String getTest() { return this.test; } public Demo() { } }
可以看见在Demo.class文件中,已经成功生成了test和value的get方法。
setter方法也可以通过此方式实现。
本文来自博客园,作者:jkbolck,转载请注明原文链接:https://www.cnblogs.com/lwjblogs/p/15740623.html