2019-11-22 记一次BeanUtils的优化

业务中存在大量的request -> domin -> response的类型转换
由于懒,不想写这么多参数赋值,所以有了以下

为了方便写一个反射方法

public static  T reflectionAttr(F f, Class t) {
        try {
            Field[] fields1 = f.getClass().getDeclaredFields();
            T t1 = t.getDeclaredConstructor().newInstance();
            Field[] fields2 = t1.getClass().getDeclaredFields();
            for (Field f1 : fields1) {
                for (Field f2 : fields2) {
                    if (f1.getName().equals(f2.getName())) {
                        handler(f1, f2, f, t1);
                    }
                }
            }
            return t1;
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
        return null;
    }

    private static  void handler(Field f1, Field f2, F f, T t1) throws Exception {
        Class type = f1.getType();
        if (type.isEnum()) {
            //处理枚举
            Object[] enumConstants = f2.getType().getEnumConstants();
            for (Object ob : enumConstants) {
                if (ob.toString().equals(f1.get(f).toString())) {
                    f2.set(t1, ob);
                }
            }
        } else if (type == ObjectId.class) {
            //处理objectId
            f2.set(t1, f1.get(f).toString());
        } else {
            f2.set(t1, f1.get(f));
        }
    }

优势:所有类中参数名一样的值都可以直接赋值
缺点:由于使用反射+大量for循环 在重复百万次时速度差10-20倍

考虑其它方案:
代码生成:通过模板生成对应的方法
核心组件velocity
流程:
1.创建模板
2.加载模块
3.加载数据
4.生成代码

记一个经验:******
在创建模板后,生成的代码的存在对不齐的问题。即,如何按自己的想法创建格式规范的代码;
在经过10多次调试之后~~
理论上来说,你在模板里怎么写就会生成对应格式的代码
但是在使用for循环,if判断时,要了解到,这些特殊字符前的符号也是站位的,而这些也是造成对不齐最大的原因,尽可能将for,if顶格写,需要追加的字符串前需要多少空格或者tab就直接加即可;
下面是一个包含增删改查的service模板

/**
 * @author ${author}
 */
public class ${className}Service {
    @Inject
    Repository<${className}> ${classname}Repository;

    public Create${className}Response create(Create${className}Request request) {
        ${className} ${classname} = new ${className}();
#foreach ($column in $columns)#if($column.attrType == "LocalDateTime")
        ${classname}.${column.attrname} = LocalDateTime.now();
#elseif($column.attrType == "LocalDate")
        ${classname}.${column.attrname} = LocalDate.now();
#elseif($column.extra == "auto_increment")
#elseif($column.dataType=="enum")
        ${classname}.${column.attrname} = Enum.valueOf(${column.attrName}.class, request.${column.attrname}.toString());
#else
        ${classname}.${column.attrname} = request.${column.attrname};
#end
#end
        ${classname}.id = ${classname}Repository.insert(${classname}).orElseThrow(() -> new RuntimeException("create ${classname} failed"));
        Create${className}Response create${className}Response = new Create${className}Response();
#foreach ($column in $columns)#if($column.dataType=="enum")
        create${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
        create${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
        return create${className}Response;
    }

    private ${className} get(Long id) {
        return ${classname}Repository.get(id).orElseThrow(() -> new NotFoundException("${classname} not found"));
    }

    public Update${className}Response update(Long id, Update${className}Request request) {
        ${className} ${classname} = get(id);
#foreach ($column in $columns)#if($column.attrname.indexOf("created")!=-1)
#elseif($column.attrType == "LocalDate")
        ${classname}.${column.attrname} = LocalDate.now();
#elseif($column.extra == "auto_increment")
#elseif($column.attrType == "LocalDateTime")
        ${classname}.${column.attrname} = LocalDateTime.now();
#elseif($column.dataType=="enum")
        ${classname}.${column.attrname} = Enum.valueOf(${column.attrName}.class, request.${column.attrname}.toString());
#else
        ${classname}.${column.attrname} = request.${column.attrname};
#end
#end
        ${classname}Repository.update(${classname});
        Update${className}Response update${className}Response = new Update${className}Response();
#foreach ($column in $columns)#if($column.dataType=="enum")
        update${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
        update${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
        return update${className}Response;
    }

    public Get${className}Response getView(Long id) {
        ${className} ${classname} = get(id);
        Get${className}Response get${className}Response = new Get${className}Response();
#foreach ($column in $columns)#if($column.dataType=="enum")
        get${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
        get${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
        return get${className}Response;
    }

    public Search${className}Response search(Search${className}Request request) {
        Query<${className}> query = ${classname}Repository.select();
        query.skip(request.skip);
        query.limit(request.limit);

        Search${className}Response search${className}Response = new Search${className}Response();
        search${className}Response.total = query.count();
        search${className}Response.${tableName} = query.fetch()
            .stream().map(${classname} -> {
                Search${className}Response.${className} search${className} = new Search${className}Response.${className}();
#foreach ($column in $columns)#if($column.dataType=="enum")
                Search${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
                Search${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
                return search${className};
            }).collect(Collectors.toList());
        return search${className}Response;
    }

    public void delete(Long id) {
        get(id);
        ${classname}Repository.delete(id);
    }
}

经验2:刚开始调试模板的,总要重启项目才能重新加载,在idea中加如jrebel插件后,每次改完模板,点击build即可,不用重启项目,加快调式速度

你可能感兴趣的:(2019-11-22 记一次BeanUtils的优化)