Java 样板代码库 Lombok 使用详解
<p>Lombok 是一个 Java 库,通过注解自动生成常用的样板代码(如 getter/setter、构造函数、日志声明等),显著减少代码量,同时提高代码整洁度。</p><h2 id="一配置方法">一、配置方法</h2>
<p>(1)IDE:需安装 Lombok 插件(IntelliJ IDEA/Eclipse)</p>
<p>(2)构建工具:Maven/Gradle 添加依赖,如下:</p>
<pre><code class="language-xml"><dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</code></pre>
<h2 id="二技术原理">二、技术原理</h2>
<p>Lombok 在编译期间通过注解处理器(Annotation Processor)修改抽象语法树(AST),直接生成字节码,因此不会影响运行时性能。</p>
<h2 id="三优缺点">三、优缺点</h2>
<h3 id="1-优点">1. 优点</h3>
<p>(1)减少样板代码,提升可读性。</p>
<h3 id="2-缺点">2. 缺点</h3>
<p>(1)隐藏了实际代码,可能增加调试难度</p>
<p>(2)需团队统一规范,避免滥用</p>
<h2 id="四功能介绍">四、功能介绍</h2>
<h3 id="1-简化-pojo-类代码">1. 简化 POJO 类代码</h3>
<p>(1)@Getter / @Setter</p>
<p>作用:自动生成字段的 getter/setter 方法。</p>
<p>示例:</p>
<pre><code class="language-java">@Getter
@Setter
public class Student {
}
@Getter
@Setter
private String name;
</code></pre>
<p>扩展:可通过 <code>AccessLevel</code> 指定访问级别(如 <code>@Getter(AccessLevel.PROTECTED)</code>)。</p>
<p>(2) @ToString</p>
<p>作用:生成 <code>toString()</code> 方法,包含所有字段或指定字段。</p>
<p>示例:</p>
<pre><code class="language-java">@ToString(exclude = "password")
public class User { ... }
</code></pre>
<p>(3)@EqualsAndHashCode</p>
<p>作用:生成 <code>equals()</code> 和 <code>hashCode()</code> 方法,默认使用所有非静态字段。</p>
<p>示例:</p>
<pre><code class="language-java">@EqualsAndHashCode(callSuper = true) // 包含父类字段
</code></pre>
<p>(4)@NoArgsConstructor</p>
<p>生成无参构造方法,force 参数可强制初始化 final 字段为 0/false/null。</p>
<p>(5)@RequiredArgsConstructor</p>
<p>为 final 字段和@NonNull 字段生成构造方法,适合依赖注入场景。</p>
<p>(6)@AllArgsConstructor</p>
<p>生成全参构造方法,按字段声明顺序排列参数。</p>
<p>(7)@Data</p>
<p>作用:组合注解,包含 <code>@Getter</code>、<code>@Setter</code>、<code>@ToString</code>、<code>@EqualsAndHashCode</code> 和 <code>@RequiredArgsConstructor</code>。</p>
<p>适用场景:POJO 类简化。</p>
<p>(8)@Value</p>
<p>作用:生成不可变类(所有字段为 <code>final</code>),组合 <code>@Getter</code>、<code>@ToString</code>、<code>@EqualsAndHashCode</code> 等。</p>
<p>示例:</p>
<pre><code class="language-java">@Value
public class Point {
int x;
int y;
}
</code></pre>
<p>(9)@With</p>
<p>作用:生成不可变对象的副本并修改指定字段(类似 Kotlin 的 <code>copy</code>)。</p>
<p>示例:</p>
<pre><code class="language-java">@With
@AllArgsConstructor
public class User {
private String name;
}
User user = new User("Alice").withName("Bob");
</code></pre>
<h3 id="2-简化逻辑代码">2. 简化逻辑代码</h3>
<p>(1)@Builder</p>
<p>作用:提供建造者模式 API。</p>
<p>示例:</p>
<pre><code class="language-java">@Builder
public class User {
private String name;
private int age;
}
// 使用
User user = User.builder().name("Alice").age(25).build();
</code></pre>
<p>注意:@Builder 会生成一个私有的全参构造函数,导致无法实例化对象。</p>
<p>(2) @SneakyThrows</p>
<p>作用:偷偷抛出受检异常,无需显式声明 <code>throws</code>。</p>
<p>示例:</p>
<pre><code class="language-java">@SneakyThrows(IOException.class)
public void readFile() {
Files.readAllBytes(Paths.get("file.txt"));
}
</code></pre>
<p>(3) @Cleanup</p>
<p>作用:自动调用资源的 <code>close()</code> 方法(如 IO 流)。</p>
<p>示例:</p>
<pre><code class="language-java">@Cleanup InputStream in = new FileInputStream("file.txt");
</code></pre>
<h3 id="3-扩展变量类型">3. 扩展变量类型</h3>
<p>(1) val</p>
<p>标识变量为 final 局部变量。</p>
<p>(2) var</p>
<p>用于局部变量类型推断。类似于 Java 10+ 的 var,所以JDK 10 以上不建议使用。</p>
<h3 id="4-日志注解">4. 日志注解</h3>
<p>(1)注解与对应框架</p>
<table>
<thead>
<tr>
<th>注解</th>
<th>对应的日志框架</th>
<th>依赖示例(Maven)</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@Log</code></td>
<td><code>java.util.logging</code> (JUL)</td>
<td>内置(无需额外依赖)</td>
</tr>
<tr>
<td><code>@Log4j</code></td>
<td>Apache Log4j 1.x</td>
<td><code>log4j:log4j:1.2.17</code></td>
</tr>
<tr>
<td><code>@Log4j2</code></td>
<td>Apache Log4j 2.x</td>
<td><code>org.apache.logging.log4j:log4j-core:2.x</code></td>
</tr>
<tr>
<td><code>@Slf4j</code></td>
<td>SLF4J(需绑定具体实现,如 Logback)</td>
<td><code>org.slf4j:slf4j-api:1.7.x</code></td>
</tr>
<tr>
<td><code>@XSlf4j</code></td>
<td>SLF4J 扩展(支持 MDC、标记等)</td>
<td>同 <code>@Slf4j</code></td>
</tr>
<tr>
<td><code>@CommonsLog</code></td>
<td>Apache Commons Logging</td>
<td><code>commons-logging:commons-logging:1.2</code></td>
</tr>
<tr>
<td><code>@Flogger</code></td>
<td>Google Flogger</td>
<td><code>com.google.flogger:flogger:0.7.x</code></td>
</tr>
<tr>
<td><code>@JBossLog</code></td>
<td>JBoss Logging</td>
<td><code>org.jboss.logging:jboss-logging:3.4.x</code></td>
</tr>
</tbody>
</table>
<p>(2)自定义日志变量名</p>
<p>通过 <code>topic</code> 参数修改日志实例名称。</p>
<p>示例代码:</p>
<pre><code class="language-java">@Slf4j(topic = "AuditLogger")
public class Service {
public void run() {
log.info("Audit event"); // 使用名为 AuditLogger 的日志实例
}
}
</code></pre>
<p>(3)日志级别支持</p>
<p>自动生成 <code>trace()</code>、<code>debug()</code>、<code>info()</code>、<code>warn()</code>、<code>error()</code> 等方法。</p>
<p>(4)<code>@XSlf4j</code> 的 MDC 支持</p>
<p>结合 SLF4J 的 Mapped Diagnostic Context(MDC)实现日志上下文跟踪。</p>
<p>示例代码:</p>
<pre><code class="language-java">@XSlf4j
public class OrderService {
public void processOrder(String orderId) {
MDC.put("orderId", orderId);
log.info("Processing order"); // 日志中自动包含 orderId
MDC.clear();
}
}
</code></pre>
<p>(5)<code>@Flogger</code> 的性能优化</p>
<p>Google Flogger 专为高性能日志设计,支持延迟参数计算。</p>
<p>示例代码:</p>
<pre><code class="language-java">@Flogger
public class NetworkService {
public void sendRequest() {
log.atInfo().log("Request sent to %s", getRemoteHost()); // 仅当日志级别为 INFO 时计算参数
}
}
</code></pre>
<h3 id="5-锁相关注解">5. 锁相关注解</h3>
<p>(1)@Synchronized</p>
<p>实现 synchronized 同步块。</p>
<p><strong>用法:</strong></p>
<pre><code class="language-java">import lombok.Synchronized;
public class SynchronizedExample {
private final Object readLock = new Object();
@Synchronized
public static void hello() {
System.out.println("world");
}
@Synchronized
public int answerToLife() {
return 42;
}
@Synchronized("readLock")
public void foo() {
System.out.println("bar");
}
}
</code></pre>
<p><strong>实际运行代码:</strong></p>
<pre><code class="language-java">public class SynchronizedExample {
private static final Object $LOCK = new Object;
private final Object $lock = new Object;
private final Object readLock = new Object();
public static void hello() {
synchronized($LOCK) {
System.out.println("world");
}
}
public int answerToLife() {
synchronized($lock) {
return 42;
}
}
public void foo() {
synchronized(readLock) {
System.out.println("bar");
}
}
}
</code></pre>
<p>(2)@Locked</p>
<p>实现 ReentrantReadWriteLock 和 ReentrantLock 锁。</p>
<p><strong>用法:</strong></p>
<pre><code class="language-java">import lombok.Locked;
public class LockedExample {
private int value = 0;
@Locked.Read
public int getValue() {
return value;
}
@Locked.Write
public void setValue(int newValue) {
value = newValue;
}
@Locked("baseLock")
public void foo() {
System.out.println("bar");
}
}
</code></pre>
<p><strong>实际运行代码:</strong></p>
<pre><code class="language-java">public class LockedExample {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock baseLock = new ReentrantLock();
private int value = 0;
public int getValue() {
this.lock.readLock().lock();
try {
return value;
} finally {
this.lock.readLock().unlock();
}
}
public void setValue(int newValue) {
this.lock.writeLock().lock();
try {
value = newValue;
} finally {
this.lock.writeLock().unlock();
}
}
public void foo() {
this.baseLock.lock();
try {
System.out.println("bar");
} finally {
this.baseLock.unlock();
}
}
}
</code></pre>
<h2 id="五使用注意事项">五、使用注意事项</h2>
<h3 id="1-谨慎使用data可能生成不必要的方法影响性能">1. 谨慎使用@Data,可能生成不必要的方法影响性能</h3>
<p>@Data 注解会默认生成以下方法:toString()、equals()、hashCode()、getter/setter 方法、无参构造器,在大型项目中,自动生成这些方法可能会导致:性能损耗(如频繁调用<br>
hashCode())、代码可读性下降、潜在的循环引用等问题。</p>
<h3 id="2-部分注解不适用于继承场景需特殊处理">2. 部分注解不适用于继承场景需特殊处理</h3>
<p>部分注解在继承场景下需要特殊处理:</p>
<p>(1)@Builder 注解在父类使用时,子类需要手动实现构建器</p>
<p>(2)@AllArgsConstructor 不会包含父类的字段</p>
<p>(3)@Value 注解会使类变为 final,影响继承</p>
<h2 id="六总结建议">六、总结建议</h2>
<p>从实际使用情况看,Lombok 既能简化通用代码,又能使代码更简洁,未遇过明显问题,可推广应用。</p>
<h2 id="七参考文档">七、参考文档</h2>
<p>(1)lombok features</p><br><br>
来源:https://www.cnblogs.com/zengzuo613/p/18903459/lombok
頁:
[1]