返回 Skill 列表
extension
分类: 开发与工程无需 API Key

lombok

Project Lombok用于减少Java样板代码。涵盖getter、setter、构造函数、构建器、日志等注解。基于castellino和gestionale-presenze项目中的生产模式。使用时机:用户提到“lombok”、“@Data”、“@Builder”、“@Slf4j”,询问关于“减少样板代码”、“getter/setter”、“@RequiredArgsConstructor”、“@Value”。不要用于:Java语言特性 - 请改用`java`技能;不要用于:MapStruct集成 - 请改用`mapstruct`技能;不要用于:Spring注解 - 请改用`backend-spring-boot`技能

person作者: jakexiaohubgithub

Project Lombok

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: lombok for comprehensive documentation.

Maven Configuration

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.34</version>
    <optional>true</optional>
</dependency>

<!-- For MapStruct compatibility -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
</dependency>

Common Annotations

@Data (All-in-One)

@Data
public class User {
    private Long id;
    private String name;
    private String email;
}

// Generates:
// - @Getter for all fields
// - @Setter for all non-final fields
// - @ToString
// - @EqualsAndHashCode
// - @RequiredArgsConstructor

@Getter / @Setter

public class User {
    @Getter @Setter
    private String name;

    @Getter // Read-only
    private final String email;

    @Setter(AccessLevel.PROTECTED)
    private String internalId;
}

@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor

@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String name;
}

@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository; // Included in constructor
    private final UserMapper userMapper;         // Included in constructor
    private String cacheName;                    // NOT included
}

@Builder

@Data
@Builder
public class User {
    private Long id;
    private String name;
    private String email;
    @Builder.Default
    private UserStatus status = UserStatus.ACTIVE;
}

// Usage
User user = User.builder()
    .name("John")
    .email("john@example.com")
    .build();

// With toBuilder for updates
User updated = user.toBuilder()
    .name("Jane")
    .build();

@Value (Immutable)

@Value
public class UserResponse {
    Long id;
    String name;
    String email;
    LocalDateTime createdAt;
}

// Generates:
// - All fields are private final
// - @AllArgsConstructor
// - @Getter (no setters)
// - @ToString
// - @EqualsAndHashCode

Entity Pattern

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(unique = true, nullable = false)
    private String email;

    @Enumerated(EnumType.STRING)
    @Builder.Default
    private UserStatus status = UserStatus.ACTIVE;

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;

    // Exclude from toString/equals for performance
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;
}

Service Pattern with Constructor Injection

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    @Override
    public UserResponse create(CreateUserRequest dto) {
        log.info("Creating user: {}", dto.getEmail());
        User user = userMapper.toEntity(dto);
        return userMapper.toResponse(userRepository.save(user));
    }
}

Logging

@Slf4j  // SLF4J logger
public class UserService {
    public void process() {
        log.info("Processing...");
        log.debug("Debug info: {}", data);
        log.error("Error occurred", exception);
    }
}

@Log4j2  // Log4j2 logger
@CommonsLog  // Apache Commons Logging
@JBossLog  // JBoss Logging

DTO Pattern

// Request DTO
@Data
public class CreateUserRequest {
    @NotBlank
    private String name;
    @Email
    private String email;
    @Size(min = 8)
    private String password;
}

// Response DTO (immutable)
@Value
@Builder
public class UserResponse {
    Long id;
    String name;
    String email;
    UserStatus status;
    LocalDateTime createdAt;
}

@Cleanup

public void readFile(String path) throws IOException {
    @Cleanup InputStream in = new FileInputStream(path);
    // in.close() called automatically
}

@SneakyThrows

@SneakyThrows  // Wraps checked exception
public String readConfig() {
    return Files.readString(Path.of("config.json"));
}

@Synchronized

public class Counter {
    @Synchronized
    public void increment() {
        // Thread-safe
    }
}

@With (Immutable Updates)

@Value
@With
public class Point {
    int x;
    int y;
}

Point p1 = new Point(1, 2);
Point p2 = p1.withX(5);  // Point(5, 2)

Key Annotations

| Annotation | Purpose | |------------|---------| | @Data | Getter, Setter, ToString, Equals, Constructor | | @Value | Immutable class | | @Builder | Builder pattern | | @RequiredArgsConstructor | Constructor for final fields | | @Slf4j | Logger field | | @ToString.Exclude | Exclude from toString | | @EqualsAndHashCode.Exclude | Exclude from equals/hashCode |


When NOT to Use This Skill

| Scenario | Use Instead | |----------|-------------| | Java core language | java skill | | MapStruct mapping | mapstruct skill | | Spring annotations | backend-spring-boot skill | | JPA entities complex logic | Manual implementation | | Public API design | Explicit methods for clarity |


Anti-Patterns

| Anti-Pattern | Why It's Bad | Correct Approach | |--------------|--------------|------------------| | @Data on JPA entities | toString/equals issues | Use @Getter/@Setter selectively | | Not excluding lazy relations | LazyInitializationException | Use @ToString.Exclude | | @EqualsAndHashCode on entities | Proxy issues | Use @EqualsAndHashCode(onlyExplicitlyIncluded = true) | | @SneakyThrows everywhere | Hides exceptions | Use proper exception handling | | @Builder without @Default | Null fields | Add @Builder.Default | | @Value with mutable fields | Breaks immutability | Use only immutable types | | Mixing @Data and manual methods | Confusing API | Be consistent | | Not configuring in lombok.config | Inconsistent behavior | Use lombok.config file |


Quick Troubleshooting

| Issue | Cause | Solution | |-------|-------|----------| | "Cannot find symbol" for getters | IDE not processing | Enable annotation processing | | LazyInitializationException | toString on lazy relation | Add @ToString.Exclude | | MapStruct not working | Wrong processor order | Lombok before MapStruct | | Builder missing fields | No @Builder.Default | Add defaults or check config | | StackOverflowError in equals | Circular reference | Exclude relation fields | | IDE shows errors but compiles | IDE cache | Invalidate caches/restart | | @Slf4j logger not found | SLF4J not in classpath | Add SLF4J dependency | | Generated code not visible | delombok needed | Run delombok task |


Reference Documentation

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: lombok for comprehensive documentation.