领域驱动模型转换DTO -> PO

897 阅读2分钟

类图

image.png

代码

转换器接口IConvertor

import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public interface IConvertor<D extends DomainModel, P extends BasePo> {

    D convert(P po);

    P convert(D model);

    /**
     * @param poList 数据库映射实体类
     * @return
     */
    List<D> convert2ModelList(List<P> poList);

    List<P> convert2PoList(List<D> modelList);
}

转换器抽象类,增加了根据当前类参数泛型获取对应的领域模型或数据库实体方法

package com.xy.ddd.core.convertor;

import com.xy.ddd.core.model.DomainModel;
import com.xy.ddd.core.po.BasePo;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public abstract class AbstractConvertor<D extends DomainModel, P extends BasePo> implements IConvertor<D, P>{
    /**
     * @param poList 数据库映射实体类
     * @return
     */
    @Override
    public List<D> convert2ModelList(List<P> poList) {
        if (CollectionUtils.isEmpty(poList)) {
            return new ArrayList<>();
        }
        List<D> list = poList.stream().map(po -> convert(po)).collect(Collectors.toList());
        return list;
    }

    @Override
    public List<P> convert2PoList(List<D> modelList) {
        if (CollectionUtils.isEmpty(modelList)) {
            return new ArrayList<P>();
        }
        List<P> list = modelList.stream().map(model -> convert(model)).collect(Collectors.toList());
        return list;
    }

    public Class<D> getDomainModelClass() {
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            return (Class)((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
        }
        throw new IllegalStateException("未定转换器泛型");
    }

    public Class<P> getPoClass() {
        Type genericSuperclass = this.getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            return (Class)((ParameterizedType) genericSuperclass).getActualTypeArguments()[1];
        }
        throw new IllegalStateException("未定转换器泛型");
    }
}

默认实现

package com.xy.ddd.core.convertor;

import com.alibaba.fastjson.JSONObject;
import com.xy.ddd.core.annotations.DomainField;
import com.xy.ddd.core.config.DomainRegistryFactory;
import com.xy.ddd.core.constant.LogConstant;
import com.xy.ddd.core.model.DomainModel;
import com.xy.ddd.core.po.BasePo;
import com.xy.ddd.core.service.IDomainService;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.util.Assert;

import java.beans.IntrospectionException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;

public class DefaultConvertor<D extends DomainModel, P extends BasePo> extends AbstractConvertor<D, P> {

    private final List<String> ignoreField = Arrays.asList("serialVersionUID");

    @Override
    public D convert(P po) {
        Class<D> domainModelClass = getDomainModelClass();
        if (domainModelClass == null || po == null) {
            return null;
        }
        D domainModel = null;
        try {
            domainModel = domainModelClass.newInstance();
        } catch (Exception e) {
            LogConstant.frameworkLogger.error("DomainModel实例化失败, PO = {}", JSONObject.toJSON(po), e);
            return null;
        }

        if (domainModel == null) {
            LogConstant.frameworkLogger.warn("DomainModel实例化失败, PO = {}", JSONObject.toJSON(po));
            return null;
        }

        Field[] domainFields = FieldUtils.getAllFields(domainModel.getClass());

        try {
            for (Field field : domainFields) {
                writeProperty(field, po, domainModel);
            }
        } catch (Exception e) {
            LogConstant.frameworkLogger.error("DomainModel属性赋值异常, PO = {}", JSONObject.toJSON(po), e);
            return null;
        }

        return domainModel;
    }

    @Override
    public P convert(D model) {
        Class<P> poClass = getPoClass();
        if (model == null || poClass == null) {
            return null;
        }

         P po = null;
        try {
            po = poClass.newInstance();
        } catch (Exception e) {
            LogConstant.frameworkLogger.error("PoClass实例化失败, model = {}", JSONObject.toJSON(model), e);
            return null;
        }

        if (po == null) {
            LogConstant.frameworkLogger.warn("PoClass实例化失败, model = {}", JSONObject.toJSON(model));
            return null;
        }

        Field[] poFields = FieldUtils.getAllFields(po.getClass());

        try {
            for (Field field : poFields) {
                writeProperty(field, model, po);
            }
        } catch (Exception e) {
            LogConstant.frameworkLogger.error("PoClass属性赋值异常, model = {}", JSONObject.toJSON(model), e);
            return null;
        }

        return po;
    }

    Object readProperty(Field field, Object source) throws IllegalAccessException {
        Assert.notNull(source, "field must not be null");
        Assert.notNull(source, "Source must not be null");

        field.setAccessible(true);
        return field.get(source);
    }

    void writeProperty(Field field, Object source, Object target) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
        Assert.notNull(field, "field must not be null");
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");

        Object fieldValue = readProperty(field, source);

        if (fieldValue == null || ignoreField.contains(field.getName())) {
            return;
        }

        DomainField annotation = field.getAnnotation(DomainField.class);

        if (annotation != null) {
            String domainCode = annotation.code();
            String domainField = annotation.fieldName();

            IDomainService domainService = DomainRegistryFactory.getDomainService(domainCode);

            if (domainService == null) {
                LogConstant.frameworkLogger.error("使用DomainField注解的字段,需搭配实现{@link com.xy.ddd.core.model.DomainModel}");
                return;
            }

            boolean isSingle = field.getType().getSimpleName().endsWith("List");

            Object value = FieldUtils.readDeclaredField(source, domainField);

            if (isSingle) {
                D domainModel = (D) domainService.findOneByField(domainField, value);
                FieldUtils.writeDeclaredField(target, field.getName(), domainModel);
            } else {
                List<D> list = domainService.findListByField(domainField, value);
                FieldUtils.writeDeclaredField(target, field.getName(), list);
            }

        } else {
            FieldUtils.writeDeclaredField(target, field.getName(), fieldValue);
        }
    }

}

git

gitee.com/fly67/ddd-f…