Lombok Tool: Introduction to Common Annotations (Full)

Article directory


introduce

Official website: https://projectlombok.org/

Lombok is a Java development plug-in that enables Java developers to eliminate redundant and cumbersome code in business engineering through some annotations defined by it, especially for simple Java model objects (POJO).

After using the Lombok plug-in in the development environment, Java developers can save a lot of time on repeated construction, methods such as hashCode and equals, and methods such as accessor and ToString of various business object models. For these methods, it can automatically generate these methods for us during the compilation of the source code , and does not reduce the performance of the program like reflection.

Import Maven dependency

Using the latest version 1.18.24

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

Commonly used annotations

@NoArgsConstructor /@ AllArgsConstructor

  • @NoArgsConstructor/@AllArgsConstructor is to generate a parameterless constructor and a constructor containing all parameters for this class

Test case 1:

@AllArgsConstructor
public class Demo extends Parent{
    
    
    private String name;
    private int age;
}

@AllArgsConstructor
@NoArgsConstructor
class Parent {
    
    
    private Integer id;
}

The compiled two class files are as follows:

This annotation does not take the attribute id of the parent class into the Demo constructor, which is something to pay attention to.

public class Demo {
    
    
    private String name;
    private int age;

    public Demo() {
    
    
    }

    public Demo(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}

class Parent {
    
    
    private Integer id;

    public Parent(Integer id) {
    
    
        this.id = id;
    }

    public Parent() {
    
    
    }
}

Through IDEA's class structure, you can also see what is generated


Test case 2:

Through @AllArgsConstructor ( access = AccessLevel.PROTECTED), you can specify the access rights of the constructor

@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Demo{
    
    
    private String name;
    private int age;
}

Generated after compilation:

public class Demo {
    
    
    private String name;
    private int age;

    protected Demo(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}


Test case 3:

@AllArgsConstructor(access = AccessLevel.PROTECTED, staticName = “test”)

@AllArgsConstructor(access = AccessLevel.PROTECTED, staticName = "test")
public class Demo{
    
    
    private final int finalVal = 10;
    private String name;
    private int age;
}

After compilation:

public class Demo {
    
    
    private String name;
    private int age;

    private Demo(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    protected static Demo test(String name, int age) {
    
    
        return new Demo(name, age);
    }
}

The above effect is: you can specify the access rights of the generated constructor. But if a static method is specified, then the constructor will be automatically private , and access is only provided through the static method, and we found that the final attribute value will not be put into the constructor.

@NoArgsConstructor is used in the same way as @AllArgsConstructor

@RequiredArgsConstructor

The @RequiredArgsConstructor annotation will generate all corresponding constructors in @NonNull注解 / org.jetbrains.annotations.NotNull注解the final修饰的成员变量class

Test Case:

@RequiredArgsConstructor
public class Demo {
    
    

    @NonNull
    private final int finalVal;
    @NonNull
    private String name;
    @NonNull
    private int age;
}

Generated after compilation:

import lombok.NonNull;

public class Demo {
    
    
    @NonNull
    private final int finalVal;
    @NonNull
    private String name;
    @NonNull
    private int age;

    public Demo(@NonNull int finalVal, @NonNull String name, @NonNull int age) {
    
    
        if (name == null) {
    
    
            throw new NullPointerException("name is marked non-null but is null");
        } else {
    
    
            this.finalVal = finalVal;
            this.name = name;
            this.age = age;
        }
    }
}

Explanation: This annotation will identify @NonNull fields and final modified fields, and then generate a constructor with this field as an element.

If all fields have no @NonNull annotation, the effect is the same as @NoArgsConstructor;
the parameters of @RequiredArgsConstructor annotation are the same as the other two annotations

Note: Of course, these three constructor annotations require that member variables are non-static, otherwise static variables will not be assigned in the constructor

@Getter/@Setter

This pair of annotations is easy to understand from the name. When used on member variables or classes, it is equivalent to generating corresponding get and set methods for member variables. At the same time, you can also specify access modifiers for the generated methods . Of course, the default is public

// 如果指定在类上,所有字段都会生成get/set方法
// 指定在字段上, 只有标注的字段才会生成get/set方法
@Getter
@Setter
public class Demo {
    
    

    private String name;
    private int age;
}

These two annotations are directly used on the class, and corresponding get and set methods can be generated for all non-static member variables in this class. If it is a final variable, there will only be a get method

@ToString/@EqualsAndHashCode

These two annotations are also relatively easy to understand, that is, toString, equals and hashcode methods are generated, and the latter also generates a canEqual method to determine whether an object is an instance of the current class. Only non-static member variables in the class are used when generating methods.

@ToString
@EqualsAndHashCode
public class Demo {
    
    

    private String name;
    private int age;
}

Some key properties can control the output of toString, we can find out:

//@EqualsAndHashCode也有类似的下面的属性,
@ToString(
        includeFieldNames = true, //是否使用字段名
        exclude = {
    
    "name"}, //排除某些字段
        of = {
    
    "age"}, //只使用某些字段
        callSuper = true //是否让父类字段也参与 默认false
)

@Data

Equivalent to annotation collection. The effect is equivalent to @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor and the effect of these 5 annotations

It should be noted that @NoArgsConstructor and @AllArgsConstructor are not included here

  • Therefore, when using @Data in general, it should be used together with these two annotations
@Data
public class Demo {
    
    
    private String name;
    private int age;
}

@Builder

@Builder provides a more respected way of building value objects; a very recommended way of building value objects.

The disadvantage is that the properties of the parent class cannot be produced in the builder

A class marked with @Builder will generate an inner class inside the class to generate a value object

@Builder
public class Demo {
    
    
    private final int finalVal = 10;

    private String name;
    private int age;
}

Generated after compilation:

public class Demo {
    
    
    private final int finalVal = 10;
    private String name;
    private int age;

    Demo(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    public static Demo.DemoBuilder builder() {
    
    
        return new Demo.DemoBuilder();
    }

    public static class DemoBuilder {
    
    
        private String name;
        private int age;

        DemoBuilder() {
    
    
        }

        public Demo.DemoBuilder name(String name) {
    
    
            this.name = name;
            return this;
        }

        public Demo.DemoBuilder age(int age) {
    
    
            this.age = age;
            return this;
        }

        public Demo build() {
    
    
            return new Demo(this.name, this.age);
        }

        public String toString() {
    
    
            return "Demo.DemoBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

How to use:

public class Main {
    
    

    public static void main(String[] args) {
    
    
        Demo demo = Demo.builder().name("zss").age(20).build();
        System.out.println(demo);
    }
}

Generally, 90% of the Lombok annotations we mark for POJO classes are these 4: @Data, @NoArgsConstructor, @AllArgsConstructor, @Builder

@Accessors

@Accessors A more fluent annotation designed for getter and setter methods
This annotation should be used with @Getter and @Setter to modify the default form of setter and getter methods.

Detailed explanation of @Accessors attribute

  • fluent attribute: chained form is especially easy to use, method concatenation is more and more convenient
  • chain property: in a streaming form (if the value of the specified chain is not displayed, the chain will also be set to true)
  • prefix attribute: Generate getter and setter methods for properties with specified prefixes, and the generated getter and setter methods will remove the prefix

When testing without @Accessors

fluent attribute

The default is false, when the value is true, there will be no get in front of the getter method of the corresponding field, and there will be no set in the setter method.

Generated after compilation:

public class Demo {
    
    
    private final int finalVal = 10;
    private String xxName;
    private int yyAge;

    public Demo() {
    
    
    }

    public int finalVal() {
    
    
        Objects.requireNonNull(this);
        return 10;
    }

    public String xxName() {
    
    
        return this.xxName;
    }

    public int yyAge() {
    
    
        return this.yyAge;
    }

    public Demo xxName(String xxName) {
    
    
        this.xxName = xxName;
        return this;
    }

    public Demo yyAge(int yyAge) {
    
    
        this.yyAge = yyAge;
        return this;
    }

    public String toString() {
    
    
        int var10000 = this.finalVal();
        return "Demo(finalVal=" + var10000 + ", xxName=" + this.xxName() + ", yyAge=" + this.yyAge() + ")";
    }
}

use:

public class Main {
    
    

    public static void main(String[] args) {
    
    
        Demo demo = new Demo();
        // setter方法; 这里包含了chain=true的功能,可以链式设置值
        demo.xxName("lucky").yyAge(20);
        // getter方法
        System.out.println(demo.xxName() + "," + demo.yyAge());
        System.out.println("demo = " + demo);
    }
}

chain attribute

If not written, the default is false. When the value is true, after the setter method of the corresponding field is called, the current object will be returned to set the value in a chain

Generated after compilation:

public class Demo {
    
    
    private final int finalVal = 10;
    private String xxName;
    private int yyAge;

    public Demo() {
    
    
    }

    public int getFinalVal() {
    
    
        Objects.requireNonNull(this);
        return 10;
    }

    public String getXxName() {
    
    
        return this.xxName;
    }

    public int getYyAge() {
    
    
        return this.yyAge;
    }

    public Demo setXxName(String xxName) {
    
    
        this.xxName = xxName;
        return this;
    }

    public Demo setYyAge(int yyAge) {
    
    
        this.yyAge = yyAge;
        return this;
    }

    public String toString() {
    
    
        int var10000 = this.getFinalVal();
        return "Demo(finalVal=" + var10000 + ", xxName=" + this.getXxName() + ", yyAge=" + this.getYyAge() + ")";
    }
}

use

public class Main {
    
    

    public static void main(String[] args) {
    
    
        Demo demo = new Demo();
        // setter方法
        demo.setXxName("lucky").setYyAge(20);
        System.out.println("demo = " + demo);
    }
}

prefix attribute

This attribute is an array of strings. When the array has a value, it means ignoring the corresponding prefix in the field and generating the corresponding getter and setter methods.

If we add its prefix to the attribute value of @Accessors, we can call the getter and setter methods of the field as if there is no prefix.

Here just remove the prefix of the original attribute

other notes

@SneakyThrows

This annotation is used on the method , you can wrap the code in the method with a try-catch statement, catch the exception and use Lombok.sneakyThrow(e) to throw the exception in the catch, you can use the form of @SneakyThrows(Exception.class) Specifies which exception to throw

public class Demo {
    
    
    @SneakyThrows(UnsupportedEncodingException.class)
    public String utf8ToString(byte[] bytes) {
    
    
        return new String(bytes, "UTF8");
    }
}

After compiling and generating:

public class Demo {
    
    
    public String utf8ToString(byte[] bytes) {
    
    
        try {
    
    
            return new String(bytes, "UTF8");
        } catch (UnsupportedEncodingException var3) {
    
    
            throw var3;
        }
    }
}

@Value

The @Value annotation is similar to @Data, except that it defines all member variables as private final by default, and does not generate a set method.

So @Value is more suitable for more read-only classes , so it can still be used in special cases.

@Cleanup

@Cleanup can automatically release resources; the difference from try-with-resources: try-with-resources and @Cleanup of lombok

This annotation is used 局部变量to ensure that the resource represented by this variable will be automatically closed. The default is to call the close() method of the resource.

If the resource has other closing methods, you can use it @Cleanup(“methodName”)to specify the method to call. Let's use input and output streams as an example:

@SneakyThrows(Exception.class)
public static void main(String[] args) {
    
    
    @Cleanup InputStream in = new FileInputStream(args[0]);
    @Cleanup OutputStream out = new FileOutputStream(args[1]);
    byte[] b = new byte[1024];
    while (true) {
    
    
        int r = in.read(b);
        if (r == -1) break;
        out.write(b, 0, r);
    }
}

Generated after compilation:

public static void main(String[] args) {
    
    
    try {
    
    
        FileInputStream in = new FileInputStream(args[0]);

        try {
    
    
            FileOutputStream out = new FileOutputStream(args[1]);

            try {
    
    
                byte[] b = new byte[1024];

                while(true) {
    
    
                    int r = in.read(b);
                    if (r == -1) {
    
    
                        return;
                    }

                    out.write(b, 0, r);
                }
            } finally {
    
    
                if (Collections.singletonList(out).get(0) != null) {
    
    
                    out.close();
                }

            }
        } finally {
    
    
            if (Collections.singletonList(in).get(0) != null) {
    
    
                in.close();
            }

        }
    } catch (Exception var15) {
    
    
        throw var15;
    }
}

@NotNull

This annotation can be used on the parameters of member methods or constructors , and will automatically generate a non-null check for this parameter. If the parameter is null, a null pointer exception will be thrown.

//成员方法参数加上@NonNull注解
public String getName(@NonNull Person p){
    
    
    return p.getName();
}

After compiling and generating:

public String getName(@NonNull Person p){
    
    
    if(p == null){
    
    
        throw new NullPointerException("person");
    }
    return p.getName();
}

@Synchronized

Acts on the method, can replace the synchronized keyword or the lock lock

This annotation is used on class methods or instance methods. The effect is the same as the synchronized keyword. The difference is that the lock object is different. For class methods and instance methods, the lock objects of the synchronized keyword are the class object and this object of the class respectively.

The lock objects of @Synchronized are private static final object lock and private final object lock respectively. Of course, you can also specify the lock object yourself

Note: The attribute value specifies the lock object. If the lock object does not exist, the compilation will fail. The default value is ""

public class Demo {
    
    

    private Object obj;

    @Synchronized
    public static void hello() {
    
    
        System.out.println("world");
    }

    @Synchronized
    public int answerToLife() {
    
    
        return 42;
    }

    @Synchronized("obj")
    public void foo() {
    
    
        System.out.println("bar");
    }
}

Generated after compilation:

public class Demo {
    
    
    private static final Object $LOCK = new Object[0];
    private final Object $lock = new Object[0];
    private Object obj;

    public Demo() {
    
    
    }

    public static void hello() {
    
    
        synchronized($LOCK) {
    
    
            System.out.println("world");
        }
    }

    public int answerToLife() {
    
    
        synchronized(this.$lock) {
    
    
            return 42;
        }
    }

    public void foo() {
    
    
        synchronized(this.obj) {
    
    
            System.out.println("bar");
        }
    }
}

Log annotations such as @Log, @Log4j, @Slf4j, @Log4j2, @CommonsLog, @XSlf4j

For more information about logs, please refer to my blog: Log Series

These annotations have topic attributes: set the parameters of the getLogger(String name) method

These annotations are used on the class , which can omit the step of generating log objects from the log factory, and log directly.

Specific annotations vary according to different logging tools . At the same time, topic can be used in annotations to specify the class name when generating log objects. The different log annotations are summarized as follows (the above is the annotation, and the following is the actual effect):

@Log annotation

By default, a java.util.logging.Logger object will be generated, JUL

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

Using the JUL logging framework

@Log
public class LombokJULTest {
    
    
    /*
        日志入口程序
        java.util.logging.Logger
     */
     
    // @Log标注在JULTest类上,就表示自动生成了下面这行代码
    // Logger log = Logger.getLogger("com.lucky.jul.JULTest");
    @Test
    public void test01() {
    
    
        // 方式1
        log.info("输出info信息1");
        // 方式2
        log.log(Level.INFO, "输出info信息2");
    }
}

控制台输出:
八月 14, 2022 9:17:13 上午 com.lucky.jul.JULTest test01
信息: 输出info信息1
八月 14, 2022 9:17:13 上午 com.lucky.jul.JULTest test01
信息: 输出info信息2

Generated after compilation:

public class LombokJULTest {
    
    
    private static final Logger log = Logger.getLogger(LombokJULTest.class.getName());

    public LombokJULTest() {
    
    
    }

    @Test
    public void testLombokLog() {
    
    
        log.info("输出info信息1");
        log.log(Level.INFO, "输出info信息2");
    }
}

@Log4j annotation

By default, an org.apache.log4j.Logger object will be generated

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

Cases using the Log4j framework:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

log4j configuration file (under resources, log4j.properties file)

log4j.rootLogger=trace,console,
#配置appender输出方式
log4j.appender.console=org.apache.log4j.ConsoleAppender
#配置输出的格式
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern=[%-5p]%r %c%t%d{yyyy-MM-dd HH:mm:ss:SSS} %m%n

@Log4j
public class LombokLog4jTest {
    
    

    // 使用Lombok的@Log4j注解, 相当于会自动生成下面这个logger对象
    // Logger log = Logger.getLogger(LombokLog4jTest.class);

    @Test
    public void testLombokLog4j() {
    
    
        // BasicConfigurator.configure(); // 默认指定了log4j的logger,输出位置,输出格式;不需要配置文件也可以打印日志

        // debug是默认的级别, 所以不会输出trace信息
        log.fatal("fatal信息");
        log.error("error信息");
        log.warn("warn信息");
        log.info("info信息");
        log.debug("debug信息");
        log.trace("trace信息");
    }
}

控制台输出:
[FATAL]0 com.lucky.log4j.LombokLog4jTestmain2022-08-14 11:02:45:720 fatal信息
[ERROR]2 com.lucky.log4j.LombokLog4jTestmain2022-08-14 11:02:45:722 error信息
[WARN ]2 com.lucky.log4j.LombokLog4jTestmain2022-08-14 11:02:45:722 warn信息
[INFO ]3 com.lucky.log4j.LombokLog4jTestmain2022-08-14 11:02:45:723 info信息

Code generated after compilation:

public class LombokLog4jTest {
    
    
    private static final Logger log = Logger.getLogger(LombokLog4jTest.class);

    public LombokLog4jTest() {
    
    
    }

    @Test
    public void testLombokLog4j() {
    
    
        log.fatal("fatal信息");
        log.error("error信息");
        log.warn("warn信息");
        log.info("info信息");
        log.debug("debug信息");
        log.trace("trace信息");
    }
}

@Log4j2 annotation

The most excellent Java log framework, Log4j2 can also be used as a simple log facade

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

Use case: (this time using Log4j2 as a log facade to achieve simple log printing)

<dependencies>
     <!-- log4j2日志门面 -->
      <dependency>
          <groupId>org.apache.logging.log4j</groupId>
          <artifactId>log4j-api</artifactId>
          <version>2.12.1</version>
      </dependency>

      <!-- log4j2日志实现 -->
      <dependency>
          <groupId>org.apache.logging.log4j</groupId>
          <artifactId>log4j-core</artifactId>
          <version>2.12.1</version>
      </dependency>

      <!-- 异步日志依赖 -->
      <dependency>
          <groupId>com.lmax</groupId>
          <artifactId>disruptor</artifactId>
          <version>3.3.7</version>
      </dependency>
</dependencies>

Under the resources directory, log4j2.xml

<?xml version="1.0" encoding="utf-8" ?>
<Configuration status="debug">
    <!-- 配置appender -->
    <Appenders>
        <Console name="consoleAppender" target="SYSTEM_ERR">
            <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L %thread %m%n"/>
        </Console>
    </Appenders>
    <!-- 配置logger -->
    <Loggers>
        <!-- 配置root logger -->
        <Root level="trace">
            <!-- 引用appender -->
            <AppenderRef ref="consoleAppender"/>
        </Root>
    </Loggers>
</Configuration>

import lombok.extern.log4j.Log4j2;
import org.junit.Test;

@Log4j2
public class LombokLog4j2Test {
    
    

    // @Log4j2会自动生成下面的Logger对象
    // Logger log = LogManager.getLogger(Log4j2Test.class);

    @Test
    public void lombokLog4jTest() {
    
    
        log.fatal("fatal信息");
        log.error("error信息");
        log.warn("warn信息");
        log.info("info信息");
        log.debug("debug信息");
        log.trace("trace信息");
    }
}

控制台输出:
[FATAL] 2022-08-14 11:43:31.845 com.lucky.Log4j2Test lombokLog4jTest 14 main fatal信息
[ERROR] 2022-08-14 11:43:31.849 com.lucky.Log4j2Test lombokLog4jTest 15 main error信息
[WARN ] 2022-08-14 11:43:31.849 com.lucky.Log4j2Test lombokLog4jTest 16 main warn信息
[INFO ] 2022-08-14 11:43:31.849 com.lucky.Log4j2Test lombokLog4jTest 17 main info信息
[DEBUG] 2022-08-14 11:43:31.850 com.lucky.Log4j2Test lombokLog4jTest 18 main debug信息
[TRACE] 2022-08-14 11:43:31.850 com.lucky.Log4j2Test lombokLog4jTest 19 main trace信息

Generated after compilation:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;

public class LombokLog4j2Test {
    
    
    private static final Logger log = LogManager.getLogger(LombokLog4j2Test.class);

    public LombokLog4j2Test() {
    
    
    }

    @Test
    public void lombokLog4jTest() {
    
    
        log.fatal("fatal信息");
        log.error("error信息");
        log.warn("warn信息");
        log.info("info信息");
        log.debug("debug信息");
        log.trace("trace信息");
    }
}

@Slf4j annotation

Slf4j log facade (Simple Logging Facade For Java), Slf4j is mainly to provide a standard and standardized API framework for Java log access. Its main significance is to provide interfaces, and the specific implementation can be handed over to other log frameworks, such as log4j and logback wait

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

Use case: (Slf4j + Log4j2 to achieve log output)

<!-- slf4j日志门面 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>
<!-- log4j2适配器 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.12.1</version>
</dependency>

<!-- log4j2日志门面 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.12.1</version>
</dependency>

<!-- log4j2日志实现 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.12.1</version>
</dependency>

<!-- 异步日志依赖 -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.7</version>
</dependency>

Under the resources directory, log4j2.xml

<?xml version="1.0" encoding="utf-8" ?>
<Configuration status="debug">
    <!-- 配置appender -->
    <Appenders>
        <Console name="consoleAppender" target="SYSTEM_ERR">
            <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L %thread %m%n"/>
        </Console>
    </Appenders>
    <!-- 配置logger -->
    <Loggers>
        <!-- 配置root logger -->
        <Root level="trace">
            <!-- 引用appender -->
            <AppenderRef ref="consoleAppender"/>
        </Root>
    </Loggers>
</Configuration>

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

@Slf4j
public class LombokSlf4jTest {
    
    

    // @Slf4j会自动生成下面这个Logger对象
    // Logger log = LoggerFactory.getLogger(LombokSlf4jTest.class);

    @Test
    public void lombokSlf4jTest() {
    
    
        log.error("error信息");
        log.warn("warn信息");
        log.info("info信息");
        log.debug("debug信息");
        log.trace("trace信息");
    }
}

Generated after compilation:

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LombokSlf4jTest {
    
    
    private static final Logger log = LoggerFactory.getLogger(LombokSlf4jTest.class);

    public LombokSlf4jTest() {
    
    
    }

    @Test
    public void lombokSlf4jTest() {
    
    
        log.error("error信息");
        log.warn("warn信息");
        log.info("info信息");
        log.debug("debug信息");
        log.trace("trace信息");
    }
}

Other Lombok log comments, understand by yourself

@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

@Delegate

Attributes annotated by @Delegate will combine the public non-static methods of this attribute type into the current class

public class Person {
    
    

    public void personMsg() {
    
    
        System.out.println("Person.personMsg");
    }

    public String printName(String name) {
    
    
        return name;
    }

    private Integer printAge(Integer age) {
    
    
        return age;
    }

    public static void printOther() {
    
    
        System.out.println("Person.printOther");
    }
}

@Getter
@Setter
public class Demo {
    
    

    @Delegate
    private Person person;
}

Generated after compilation:

public class Demo {
    
    
    private Person person;

    public Demo() {
    
    
    }

    public Person getPerson() {
    
    
        return this.person;
    }

    public void setPerson(Person person) {
    
    
        this.person = person;
    }

    public void personMsg() {
    
    
        this.getPerson().personMsg();
    }

    public String printName(String name) {
    
    
        return this.getPerson().printName(name);
    }
}

use:

public class Main {
    
    

    public static void main(String[] args) {
    
    
        Demo demo = new Demo();
        demo.setPerson(new Person());
        demo.personMsg();
        System.out.println(demo.printName("lucky"));
    }
}

@Singular

Use @Singular to annotate a collection field (if no value attribute value is specified, then the collection field name needs to be in plural form), an add element method will be generated to add a single element to the collection

Can only be used with the @Builder annotation, which acts on fields and parameters, and is generally used in collection properties and collection parameters

use:

public class Main {
    
    

    public static void main(String[] args) {
    
    
        Demo demo = Demo.builder().name("lucky")
                .num(1).num(2).num(3)
                .build();
        System.out.println("demo = " + demo);
    }
}

控制台输出:
demo = Demo(name=lucky, nums=[1, 2, 3])

lombok: excellent blog

Guess you like

Origin blog.csdn.net/github_36665118/article/details/130647774