背景:
业务运行过程中,发现使用 Lombok的@Builder以及 @Data 共同标注的类,使用反射的时候报错。找不到无参构造方法。
@Data和@Builder 共同使用导致无参构造丢失
-
单独使用@Data注解,会生成无参数构造方法。
-
单独使用@Builder注解,生成全属性的构造方法,无无参构造方法。
-
@Data和@Builder一起用:没有了默认的构造方法。手动添加无参数构造方法或者用@NoArgsConstructor注解会报错
于是看了一下 Lombok 的 @Builder 注解源码,大致看了一下,会发现源码注解里是可以看到 无参构造没有这个细节的,但是细节很容易忽略
没有去深究它的原理,毕竟也只是一个可有可无的插件。如果仔细看一下 @Builder 的注释,会发现是没有无参构造的。
原因深究的话,可以看一下 https://projectlombok.org/features/Builder
<pre>
* @Builder
* class Example<T> {
* private T foo;
* private final String bar;
* }
* </pre>
*
* After:
*
* <pre>
* class Example<T> {
* private T foo;
* private final String bar;
*
* private Example(T foo, String bar) {
* this.foo = foo;
* this.bar = bar;
* }
*
* public static <T> ExampleBuilder<T> builder() {
* return new ExampleBuilder<T>();
* }
*
* public static class ExampleBuilder<T> {
* private T foo;
* private String bar;
*
* private ExampleBuilder() {}
*
* public ExampleBuilder foo(T foo) {
* this.foo = foo;
* return this;
* }
*
* public ExampleBuilder bar(String bar) {
* this.bar = bar;
* return this;
* }
*
* @java.lang.Override public String toString() {
* return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")";
* }
*
* public Example build() {
* return new Example(foo, bar);
* }
* }
* }
解决方式:
lombok 提供了另一个注解:
这个注解的释义也是很有意思的。
Put on any method or constructor to make lombok pretend it doesn't exist,
i.e., to generate a method which would otherwise be skipped due to possible conflicts.
这个注解可以在任何方法或者构造器上使用,这样可以使 lombok 假装这个方法或者构造器不存在。以此来达到生成由于可能存在的冲突导致跳过的方法。
package lombok.experimental;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Put on any method or constructor to make lombok pretend it doesn't exist,
* i.e., to generate a method which would otherwise be skipped due to possible conflicts.
*/
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface Tolerate {
}
于是,可以在 使用@Data和@Builder 修饰的类里加上一个@Tolerate标注的无参构造方法。
总结:
使用一个工具的时候,还是要看一下使用说明。想当然的使用可能会造成不可预估的损失。