关于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 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就可以了。可以十分有效的减少代码量。

总结

  更多深入的东西,小咸儿也没有研究,期待小咸儿的下一篇博客吧!

你可能感兴趣的:(▲项目成长▼,¤JAVA¤)