Как работает Lombok @Setter
Что проверяют
Понимаете ли вы, что Lombok работает при компиляции, и как это влияет на сборку и дизайн классов. Следом спрашивают, почему @Data на JPA-сущности плохая идея и что использовать вместо сеттеров, если объект должен быть неизменяемым.
Как отвечать
@Setter имеет RetentionPolicy.SOURCE, в байткоде аннотации нет. Lombok подключается к javac как annotation processor, но не создаёт новые файлы, как обычные процессоры, а через внутренние API компилятора дописывает методы прямо в синтаксическое дерево класса. В .class попадает обычный public void setName(String name).
Что стоит знать о поведении:
- на классе: сеттеры появляются для всех нестатических полей, кроме
final; - на поле: только для этого поля, а
@Setter(AccessLevel.NONE)исключает поле из генерации на уровне класса; - уровень доступа: задаётся как
@Setter(AccessLevel.PROTECTED), по умолчаниюpublic; - boolean: для поля
boolean activeбудетsetActive, дляboolean isActiveтожеsetActive, префиксisотбрасывается; - конфликт имён: если метод с таким именем и тем же числом параметров уже написан вручную, Lombok генерацию пропускает;
@Accessors(chain = true): сеттер возвращаетthis, аfluent = trueубирает префиксset. Глобально это настраивается вlombok.config.
В свежих JDK автоматический поиск процессоров на classpath отключён, поэтому в Maven Lombok надёжнее прописать в annotationProcessorPaths плагина компилятора. Посмотреть сгенерированный код можно через delombok.
Где спотыкаются
Говорят, что Lombok генерирует код в рантайме через рефлексию. Всё происходит при компиляции, в рантайме библиотека не нужна, поэтому её подключают со scope provided.
Вешают @Setter на весь класс по привычке. Любое поле, включая идентификатор и инварианты, становится изменяемым снаружи. Для неизменяемых объектов есть @Value, @Builder и record.
Путают @Setter с @Data. @Data добавляет ещё equals, hashCode и toString, а на JPA-сущностях это даёт ленивую загрузку внутри toString и потерянные элементы HashSet, когда после сохранения у сущности появляется ID.