Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。
Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。
pom :
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
entity :
注解意思不做说明,不清楚的可自行查资料.
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@ApiModel(value="XxxxVoimplements ",description="xxxxx")
@SuppressWarnings("serial")
public class XxxxVoimplements Serializable {
@ApiModelProperty(value = "唯一标识ID",required = true,example = "10")
@NotNull(message = "唯一标识ID不能为空")
private Long id;
}
这里仅对@Builder做下说明 :
原实例化方式 :
A a = new A(x,x,x,);
a.setX();
使用@Builder后 :
A a = A.builder().id(1l).build();
解决的问题 :
构造方法不确定,或者参数传参不确定时,可通过这个进行不同的传参.
坑1 : 空构造方法
问题 :
使用@Data注解,不增加@NoArgsConstructor, 当进行copy属性时会报错,因为无空构造函数,导致实例化失败.
解决方案 :
@Data
@NoArgsConstructor
@AllArgsConstructor
坑2 : @Builder继承
问题 :
@Builder使用extends,如B extends A, A可以使用A.builder().id(1l).build(); 但是B不能.
解决方案 :
1> 使用@SuperBuilder
2> 升级lombok版本,升级到1.18.6就可以了.
坑3 : 属性copy,实体类转换
问题 :
子类属性无法copy到父类,父类属性无法copy到子类
解决方案 :
/**
* 子类转到父类
* @param obj 转换的源对象
* @param clz 目标对象
* @return 转换后的对象
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> T transToSuper(Object obj, Class clz) {
T result = null;
try {
if (obj != null && !"".equals(obj)) {
result = (T) clz.newInstance();
Map<String, Field> destPropertyMap = new HashMap<>();
for (Field curField : clz.getDeclaredFields()) {
destPropertyMap.put(curField.getName(), curField);
}
for (Field curField : obj.getClass().getDeclaredFields()) {
Field targetField = destPropertyMap.get(curField.getName());
if (targetField != null) {
targetField.setAccessible(true);
curField.setAccessible(true);
targetField.set(result, curField.get(obj));
}
}
// **解决子类属性无法copy到父类** : getSuperclass一下即可.
for (Field curField : obj.getClass().getSuperclass().getDeclaredFields()) {
Field targetField = destPropertyMap.get(curField.getName());
if (targetField != null) {
targetField.setAccessible(true);
curField.setAccessible(true);
targetField.set(result, curField.get(obj));
}
}
// **解决父类属性无法copy到子类** : copyProperties
BeanUtils.copyProperties(obj, clz);
}
} catch (Exception e1) {
log.error("e1:{}.",e1.getMessage());
throw new BusinessException(ResultConsts.ERROR_STATUS, "实体类转换异常");
}
return result;
}
BeanUtils :
import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class BeanUtils extends BeanUtil {
/**
* <T>目标对象须含有无参构造器
* @param source 源对象
* @param c 目标对象class
* @param <T> 目标对象类型
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static <T> T copyProperties(Object source, Class<T> c) {
T t = null;
try {
t = c.newInstance();
} catch (Exception e) {
log.error("创建对象失败,可能缺少无参构造:{}", e.getMessage());
throw new RuntimeException(e);
}
BeanUtil.copyProperties(source, t);
return t;
}
/**
* 列表数据拷贝
* @param list 源对象列表
* @param c 目标对象class
* @param <T> 目标对象类型
* @return
*/
public static <T> List<T> copyProperties(List<?> list, Class<T> c) {
List<T> resultList = new ArrayList<>();
for (Object obj : list) {
T t = copyProperties(obj, c);
resultList.add(t);
}
return resultList;
}
}