前言
最近小鹹兒在開發項目的時候,寫有關插入的一條線時,需要插入到三張表中,所以傳過來的是一個組合型的model實體,這個時候就需要很多的set/get的代碼,但是經過大牛的指點,發現原來還有BeanUtils.copyProperties這個神器。十分感謝。
簡介
BeanUtils.copyProperties提供對Java反射和自省API的包裝。其主要目的是利用反射機制對JavaBean的屬性進行處理。我們知道,一個JavaBean通常包含了大量的屬性,很多情況下,對JavaBean的處理導致大量get/set代碼堆積,增加了代碼長度和閱讀代碼的難度。
過程
封裝的代碼
首先看一下小鹹兒項目中封裝的代碼,這裏用到的是重載,根據你傳的參數去匹配使用哪個方法,具體的就不多做解釋了,因爲小鹹兒也不是很懂……
// 方法一
public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
copyProperties(source, target, null, ignoreProperties);
}
// 方法二
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
@Nullable String... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
"] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null &&
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
}
catch (Throwable ex) {
throw new FatalBeanException(
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
}
}
}
}
}
具體實現
根據小鹹兒的業務需要,這裏就有三個實體是十分相似的,所以使用BeanUtils.copyProperties就會更加的方便。
public IntegralResult integralAnswer(IntegralAnswerModel integralAnswerModel) {
log.info("傳入前的IntegralAnswer實體:"+integralAnswerModel);
AnswerEntity answerEntity = new AnswerEntity();
BeanUtils.copyProperties(integralAnswerModel,answerEntity);
answerEntity.setRemark("頭腦風暴作答");
answerEntity.setId(IdWorker.nextStringId());
IntegralModel integralModel = new IntegralModel();
String[] ids = new String[]{""};
ids[0] = integralAnswerModel.getUserId();
BeanUtils.copyProperties(integralAnswerModel,integralModel);
integralModel.setPluginId("pluginId_brainstorming");
integralModel.setPrimaryId("pluginId_brainstorming");
integralModel.setReason("作答"+integralAnswerModel.getTheme()+"加分");
integralModel.setTypeKey("answer");
integralModel.setIdInfo(ids);
integralModel.setIntegral(integralAnswerModel.getLikedNumber());
RecordEntity recordEntity = new RecordEntity();
BeanUtils.copyProperties(integralAnswerModel,recordEntity);
recordEntity.setType(1);
recordEntity.setRemark("頭腦風暴作答");
recordEntity.setIntegral(integralAnswerModel.getLikedNumber());
recordEntity.setId(IdWorker.nextStringId());
log.info("傳入前的integralModel實體:"+integralModel);
IntegralResult addIntegral = integralClientService.addIntegral(integralModel);
if (IntegralResult.SUCCESS.equals(addIntegral.getCode())) {
log.info("傳入前的AnswerEntity實體:"+answerEntity);
AnswerEntity result = answerJpa.save(answerEntity);
log.info("插入後的AnswerEntity實體:"+result);
log.info("傳入前的RecordEntity實體:" +recordEntity);
RecordEntity recordResult = recordJpa.save(recordEntity);
log.info("插入後的RecordEntity實體:" +recordResult);
if (result==null){
return IntegralResult.build("1111", "頭腦風暴作答插入記錄失敗",result);
} else if (recordResult == null) {
return IntegralResult.build(IntegralResult.FAIL,"頭腦風暴作答記錄插入失敗", recordResult);
}
return IntegralResult.build("0000", "頭腦風暴作答加分成功!", addIntegral);
} else {
return IntegralResult.build("1111","頭腦風暴調用加分接口失敗", addIntegral);
}
}
個性化
如果實體還有不一樣的字段,但是我還需要該如何是好呢?
這個時候,就能看出來BeanUtils.copyProperties的好處了,如果不一樣的字段並且還需要的話,只要自己去set或者get就可以了。可以十分有效的減少代碼量。
總結
更多深入的東西,小鹹兒也沒有研究,期待小鹹兒的下一篇博客吧!