關於BeanUtils.copyProperties

前言

  最近小鹹兒在開發項目的時候,寫有關插入的一條線時,需要插入到三張表中,所以傳過來的是一個組合型的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就可以了。可以十分有效的減少代碼量。

總結

  更多深入的東西,小鹹兒也沒有研究,期待小鹹兒的下一篇博客吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章