十分钟搞懂Lombok使用与原理
1 简介Lombok是一款好用顺手的工具,就像Google Guava一样,在此予以强烈推荐,每一个Java工程师都应该使用它。Lombok是一种Java?实用工具,可用来帮助开发人员消除Java的冗长代码,尤其是对于简单的Java对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现Lombok,开发人员可以节省构建诸如hashCode()和equals()这样的方法以及以往用来分类各种accessor和mutator的大量时间。 2 IntelliJ安装Lombok
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> </dependency> 3 Lombok用法3.1 Lombok注解说明
3.2 Lombok代码示例
public static void main(String[] args) { val sets = new HashSet<String>(); val lists = new ArrayList<String>(); val maps = new HashMap<String,String>(); //=>相当于如下 final Set<String> sets2 = new HashSet<>(); final List<String> lists2 = new ArrayList<>(); final Map<String,String> maps2 = new HashMap<>(); }
public void notNullExample(@NonNull String string) { string.length(); } //=>相当于 public void notNullExample(String string) { if (string != null) { string.length(); } else { throw new NullPointerException("null"); } }
public static void main(String[] args) { try { @Cleanup InputStream inputStream = new FileInputStream(args[0]); } catch (FileNotFoundException e) { e.printStackTrace(); } //=>相当于 InputStream inputStream = null; try { inputStream = new FileInputStream(args[0]); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
@Setter(AccessLevel.PUBLIC) @Getter(AccessLevel.PROTECTED) private int id; private String shap;
@ToString(exclude = "id",callSuper = true,includeFieldNames = true) public class LombokDemo { private int id; private String name; private int age; public static void main(String[] args) { //输出LombokDemo([email?protected],name=null,age=0) System.out.println(new LombokDemo()); } }
@EqualsAndHashCode(exclude = {"id","shape"},callSuper = false) public class LombokDemo { private int id; private String shap; }
@NoArgsConstructor @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor public class LombokDemo { @NonNull private int id; @NonNull private String shap; private int age; public static void main(String[] args) { new LombokDemo(1,"circle"); //使用静态工厂方法 LombokDemo.of(2,"circle"); //无参构造 new LombokDemo(); //包含所有参数 new LombokDemo(1,"circle",2); } }
import lombok.Data; @Data public class Menu { private String shopId; private String skuMenuId; private String skuName; private String normalizeSkuName; private String dishMenuId; private String dishName; private String dishNum; //默认阈值 private float thresHold = 0; //新阈值 private float newThresHold = 0; //总得分 private float totalScore = 0; }
@Value public class LombokDemo { @NonNull private int id; @NonNull private String shap; private int age; //相当于 private final int id; public int getId() { return this.id; } ... }
@Builder public class BuilderExample { private String name; private int age; @Singular private Set<String> occupations; public static void main(String[] args) { BuilderExample test = BuilderExample.builder().age(11).name("test").build(); } }
import lombok.SneakyThrows; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.UnsupportedEncodingException; public class Test { @SneakyThrows() public void read() { InputStream inputStream = new FileInputStream(""); } @SneakyThrows public void write() { throw new UnsupportedEncodingException(); } //相当于 public void read() throws FileNotFoundException { InputStream inputStream = new FileInputStream(""); } public void write() throws UnsupportedEncodingException { throw new UnsupportedEncodingException(); } }
public class SynchronizedDemo { @Synchronized public static void hello() { System.out.println("world"); } //相当于 private static final Object $LOCK = new Object[0]; public static void hello() { synchronized ($LOCK) { System.out.println("world"); } } }
public class GetterLazyExample { @Getter(lazy = true) private final double[] cached = expensive(); private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } } // 相当于如下所示: import java.util.concurrent.atomic.AtomicReference; public class GetterLazyExample { private final AtomicReference<java.lang.Object> cached = new AtomicReference<>(); public double[] getCached() { java.lang.Object value = this.cached.get(); if (value == null) { synchronized (this.cached) { value = this.cached.get(); if (value == null) { final double[] actualValue = expensive(); value = actualValue == null ? this.cached : actualValue; this.cached.set(value); } } } return (double[]) (value == this.cached ? null : value); } private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } } 4 Lombok注解原理说道 Lombok,我们就得去提到 JSR 269: Pluggable Annotation Processing API (www.jcp.org/en/jsr/deta…) 。JSR 269 之前我们也有注解这样的神器,可是我们比如想要做什么必须使用反射,反射的方法局限性较大。首先,它必须定义@Retention为RetentionPolicy.RUNTIME,只能在运行时通过反射来获取注解值,使得运行时代码效率降低。其次,如果想在编译阶段利用注解来进行一些检查,对用户的某些不合理代码给出错误报告,反射的使用方法就无能为力了。而 JSR 269 之后我们可以在 Javac的编译期利用注解做这些事情。所以我们发现核心的区分是在 运行期 还是 编译期。 从上图可知,Annotation Processing 是在解析和生成之间的一个步骤。具体详细步骤如下: 上图是 Lombok 处理流程,在Javac 解析成抽象语法树之后(AST),Lombok 根据自己的注解处理器,动态的修改 AST,增加新的节点(所谓代码),最终通过分析和生成字节码。 自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。
IDE工具问题解决:
5 自定义支持JSR269的注解一般javac的编译过程,java文件首先通过进行解析构建出一个AST,然后执行注解处理,最后经过分析优化生成二进制的.class文件。我们能做到的是,在注解处理阶段进行一些相应处理。首先我们在META-INF.services下创建如下文件: 文件中指定我们的注解处理器:com.alipay.kris.other.lombok.MyAnnotaionProcessor,然后我们接可以编写自己的注解处理器,一个简单的实例代码如下: @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes("com.alipay.kris.other.lombok.*") public class MyAnnotaionProcessor extends AbstractProcessor { public MyAnnotaionProcessor() { super(); } @Override public boolean process(Set<? extends TypeElement> annotations,RoundEnvironment roundEnv) { for (Element elem : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) { MyAnnotation annotation = elem.getAnnotation(MyAnnotation.class); String message = "annotation found in " + elem.getSimpleName() + " with " + annotation.value(); addToString(elem); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,message); } return true; // no further processing of this annotation type } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |