Lombok,可以使用注解减少冗余代码的插件(最全讲解)

1.日志类 private static2.@date 无用信息太多3.@toString 用+连接,性能不太好4.@builder 无法复制,无法通过JSONObject转化为对象,加两个构造器
摘要由CSDN通过智能技术生成

1.简介

Lombok是一种Java的实用工具,可以用来帮助开发人员消除Java的冗长,尤其是对于简单Java对象(POJO)。它通过注解实现这一目的。

2.原理

Lombok的所有注解都是编译注解。Lombok工具是运行在编译时解析的。在这里插入图片描述
首先java文件会调用javac编译,在编译后会生成抽象语法树(AST),之后会调用插入式注解处理器处理,插入式注解处理器会修改语法树,生成一些额外的代码,经过处理器的处理语法树会有变动,有变动之后,会再次生成抽象语法树的处理环节,将变动后的代码再次生成抽象语法树,接着再通过注解处理器,如果这次语法树没有被修改,那么就会生成响应的字节码,变成class文件,以上就是注解处理器在整个javac编译源代码生成class文件中起到的作用。

3.安装

1.IDEA

1.在pom文件中引入依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>

2.安装lombok插件
点击 File->Settings->Plugins,搜索lombok,然后点击Search in repositories
在这里插入图片描述
然后选择名字为Lombok的插件,点击安装
在这里插入图片描述
插件安装完成之后一定要记得重启IDEA
重启之后Lombok插件就生效了。
测试例子:

@Getter
@Setter
@ToString
public class TestReq {
    /**
     * 测试参数1
     */
    private String param1;

    /**
     * 测试参数2
     */
    private String param2;

    public static void main(String[] args){
        TestReq req = new TestReq();
        req.setParam1("123");
        req.setParam2("456");
        System.out.println(req.toString());
    }
}

打印结果:

TestReq(param1=123, param2=456)

2.eclipse

1.在pom文件中引入依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
    <scope>provided</scope>
</dependency>

2.找到maven仓库中的lombok-1.18.8.jar
目录:maven-repository->org->projectlombok->lombok->1.18.8
在当前目录进入命令行,运行命令:java -jar .\lombok-1.18.8.jar
此时会打开lombok插件安装的可视化界面。
在这里插入图片描述
此时可以等待插件自己扫描目录,也可以点击Specify location自己指定目录
在这里插入图片描述
等出现eclipse.exe的目录之后,点击Install安装。
在这里插入图片描述
安装完成之后,点击Quit Installer退出,并且重启eclipse。
此时安装完成。进行测试

@Getter
@Setter
@ToString
public class TestReq {
    /**
     * 测试参数1
     */
    private String param1;

    /**
     * 测试参数2
     */
    private String param2;

    public static void main(String[] args){
        TestReq req = new TestReq();
        req.setParam1("123");
        req.setParam2("456");
        System.out.println(req.toString());
    }
}

打印结果:

TestReq(param1=123, param2=456)

4.注解

思维导图

在这里插入图片描述

1.日志类

1.源码

Lombok包含的日志注解一共有6类8种:
1.apachecommons:@CommonsLog

private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);

2.flogger:@Flogger

private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();

3.java:@Log

private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());

4.jbosslog:@JBossLog

private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);

5.log4j:@Log4j,@Log4j2

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);

6.slf4j:@Slf4j,@XSlf4j

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

8种注解唯一不同的只是声明的日志对象不同,其他都是一样的。用的时候根据自己使用的日志对象来选择注解。
lombok的注解仅仅针对编译阶段,它的作用只是在class文件中添加了声明对象的代码,其他没有任何作用。
@Log4j注解类源码:

/**
 * 生成日志类属性
 * 完整的的文档地址:<a href="https://projectlombok.org/features/Log">
 * 此注解会生成以下代码:
 * private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
 * 此注解对类和枚举类有效
 * 此注解生成的是org.apache.log4j.Logger对象
 * @see <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html">org.apache.log4j.Logger</a>
 * @see <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.Class)">
 */
 //此注解的类型时SOURCE,源码级别的,只有java源码能看到
 //在class中只有声明对象的代码,没有注解
@Retention(RetentionPolicy.SOURCE)
//修饰的类型时TYPE:Class, interface (including annotation type), or enum declaration
@Target(ElementType.TYPE)
public @interface Log4j {
	/** 这个参数用来声明日志对象构造器传入的类的全限定名,默认使用被打注解的类对象 */
	String topic() default "";
}
2.用法
样例1:无参

源码:

@Log4j
public class TestLogOne {}

class:

public class TestLogOne
{
  private static final Logger log = Logger.getLogger(TestLogOne.class);
}
样例2:topic参数
@Log4j(topic = "com.ding.test.lombok.log.TestLogTwo")
public class TestLogOne {}

class:

public class TestLogOne
{
  private static final Logger log = Logger.getLogger("com.ding.test.lombok.log.TestLogTwo");
}

Logger类的部分源码:

 /**
    Retrieve the appropriate {@link Logger} instance.  
 */
 public
 static 
 Logger getLogger(final String name) {
    // Delegate the actual manufacturing of the logger to the logger repository.
   return getLoggerRepository().getLogger(name);
 }

/**
    Retrieve the appropriate {@link Logger} instance.  
 */
 public
 static 
 Logger getLogger(final Class clazz) {
    // Delegate the actual manufacturing of the logger to the logger repository.
   return getLoggerRepository().getLogger(clazz.getName());
 }

从源码可以看出,传入类的全限定名和传入类对象是一致的。

3.缺点

权限修饰词默认为private,无法进行修改。涉及到继承实现等逻辑时无法使用同一个日志对象。

2.@Getter和@Setter

1.源码

@Getter

/**
 * 生成getter方法
 * 完整参考网址: <a href="https://projectlombok.org/features/GetterSetter">
 * 也可以使用@onMethod注解来给方法上加注解
 * Example:
 *     private @Getter int foo;
 * will generate:
 *     public int getFoo() {
 *         return this.foo;
 *     }
 * 此注解可以用于属性,也可以用于类
 * 当用于类时,类中所有非静态的属性都有此注解
 */
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {
	/**
	 * 如果你想让你的get方法不是公开的,可以使用此参数配置
	 */
	lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
	
	/**
	 * 这里列出的所有的注解都会放在生成的方法上
	 * 此功能的语法取决于JDK的版本
	 * up to JDK7:<br>
	 *  {@code @Getter(onMethod=@__({@AnnotationsGoHere}))}<br>
	 * from JDK8:<br>
	 *  {@code @Getter(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
	 */
	AnyAnnotation[] onMethod() default {};
	
	//是否开启懒加载
	//此参数修饰的属性必须时private final类型
	boolean lazy() default false;
	
	/**
	 * 占位符注解,可以将注解放到生成的方法上
	 * 请阅读文档,不建议使用
	 */
	@Deprecated
	@Retention(RetentionPolicy.SOURCE)
	@Target({})
	@interface AnyAnnotation {}
}

@Setter

/**
 * 生成setter方法
 * Example:
 *     private &#64;Setter int foo;
 * will generate:
 *     public void setFoo(int foo) {
 *         this.foo = foo;
 *     }
 */
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Setter {

	lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
	
	AnyAnnotation[] onMethod() default {};
	
	//这个参数的用法和onMethod基本一致
	//onMethod用于方法,onParam用于参数
	AnyAnnotation[] onParam() default {};
	
	@Deprecated
	@Retention(RetentionPolicy.SOURCE)
	@Target({})
	@interface AnyAnnotation {}
}
2.样例
样例1:无参

源码:

@Getter
@Setter
public class TestModel {
	private String param1;
	private String param2;
}

class:

public class TestModel
{
  private String param1;
  private String param2;
  
  public void setParam1(String param1)
  {
    this.param1 = param1;
  }
  
  public void setParam2(String param2)
  {
    this.param2 = param2;
  }
  
  public String getParam1()
  {
    return this.param1;
  }
  
  public String getParam2()
  {
    return this.param2;
  }
}
样例2:AccessLevel

源码:

@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PACKAGE)
public class TestModel2 {
	private String param1;
	private String param2;
}

class:

public class TestModel2
{
  private String param1;
  private String param2;
  
  void setParam1(String param1)
  {
    this.param1 = param1;
  }
  
  void setParam2(String param2)
  {
    this.param2 = param2;
  }
  
  protected String getParam1()
  {
    return this.param1;
  }
  
  protected String getParam2()
  {
    return this.param2;
  }
}

样例3:onMethod、onParam、lazy

源码:

public class TestModel3<param2> {

	@Getter(onMethod_={@Inject},lazy = true)
	private final String param1 = "123";

	@Setter(onMethod_={@Inject},onParam_={@Param("newName")})
	private String param2;
}

class:

public class TestModel3<param2>
{
  @Inject
  public String getParam1()
  {
    Object value = this.param1.get();
    if (value == null) {
      synchronized (this.param1)
      {
        value = this.param1.get();
        if (value == null)
        {
          String actualValue = "123";value = "123" == null ? this.param1 : "123";this.param1.set(value);
        }
      }
    }
    return (String)(value == this.param1 ? null : value);
  }
  
  private final AtomicReference<Object> param1 = new AtomicReference();
  private String param2;
  
  @Inject
  public void setParam2(@Param("newName") String param2)
  {
    this.param2 = param2;
  }
}

3.@ToString

1.源码
/**
 * 生成toString方法
 * 完整文档地址:<a href="https://projectlombok.org/features/ToString">
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ToString {
	/**
	 * 打印时包括每个字段的名称,默认true
	 */
	boolean includeFieldNames() default true;
	
	/**
	 * 在此参数中列出的字段将不会出现在toString方法中。
	 * 与of参数互斥,将被废弃
	 */
	String[] exclude() default {};
	
	/**
	 * 此参数中出现的字段将会出现在toString方法中
	 * 与exclude互斥,将被废弃
	 */
	String[] of() default {};
	
	/**
	 * 是否调用父类的toString方法
	 * 默认为false
	 */
	boolean callSuper() default false;
	
	/**
	 * 当值为false时,如果get方法可用,toString方法会调用get方法,没有才会直接调用属性。
	 * 当值为true时,不管有没有get方法,都直接调用属性。
	 * 默认为false
	 */
	boolean doNotUseGetters() default false;
	
	/**
	 * toString方法中只包含被@ToString.Include标记的字段
	 * 默认包含全部非静态字段
	 */
	boolean onlyExplicitlyIncluded() default false;
	
	/**
	 * 此注解标记的字段将不会出现在toString方法中
	 */
	@Target(ElementType.FIELD)
	@Retention(RetentionPolicy.SOURCE)
	public @interface Exclude {}
	
	/**
	 * 标记在属性上,会调用属性的值
	 * 标记在方法上,会调用方法的返回值
	 */
	@Target({ElementType.FIELD, ElementType.METHOD})
	@Retention(RetentionPolicy.SOURCE)
	public @interface Include {
		/**
		 * 打印的优先级,数字越高,越优先打印
		 */
		int rank() default 0;
		
		/**
		 * 打印出来的字段名
		 */
		String name() default "";
	}
}
2.样例
样例1:callSuper 、includeFieldNames

源码:

@ToString
public class TestModel {

	private String param1;
	
	@ToString(callSuper = true,includeFieldNames = true)
	class SubModel extends TestModel{
		
		private String param3;
	}
	
	@ToString(includeFieldNames = false)
	class SubModel2 extends TestModel{
		
		private String param5;
	}
}

class:

public class TestModel
{
  private String param1;
  
  public String toString()
  {
    return "TestModel(param1=" + this.param1 + ")";
  }
  
  class SubModel
    extends TestModel
  {
    private String param3;
    
    SubModel() {}
    
    public String toString()
    {
      return "TestModel.SubModel(super=" + super.toString() + ", param3=" + this.param3 + ")";
    }
  }
  
  class SubModel2
    extends TestModel
  {
    private String param5;
    
    SubModel2() {}
    
    public String toString()
    {
      return "TestModel.SubModel2(" + this.param5 + ")";
    }
  }
}

样例2:of、exclude

源码:

@ToString(of = {"param1"})
public class TestModel2{

	private String param1;
	private String param2;

	@ToString(exclude = "param3")
	class SubModel extends TestModel2{
	
		private String param3;
		private String param4;
	}
}

class:

public class TestModel2
{
  private String param1;
  private String param2;
  
  public String toString()
  {
    return "TestModel2(param1=" + this.param1 + ")";
  }
  
  class SubModel
    extends TestModel2
  {
    private String param3;
    private String param4;
    
    SubModel() {}
    
    public String toString()
    {
      return "TestModel2.SubModel(param4=" + this.param4 + ")";
    }
  }
}
样例3:onlyExplicitlyIncluded 、Exclude、Include

源码:

@ToString
public class TestModel3{
	
	@Exclude
	private String param1;
	
	@Include
	private String param2;
	
	private String param3;
	
	@ToString(onlyExplicitlyIncluded = true)
	class SubModel extends TestModel3{
		
		@Exclude
		private String param4;
		
		@Include
		private String param5;
		
		private String param6;
	}
}

class:

public class TestModel3
{
  private String param1;
  private String param2;
  private String param3;
  
  public String toString()
  {
    return "TestModel3(param2=" + this.param2 + ", param3=" + this.param3 + ")";
  }
  
  class SubModel
    extends TestModel3
  {
    private String par
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值