美文网首页
2019-11-22 记一次BeanUtils的优化

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

作者: 江江江123 | 来源:发表于2019-11-22 13:25 被阅读0次

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

    为了方便写一个反射方法

    public static <F, T> T reflectionAttr(F f, Class<T> 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 <F, T> 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的优化

          本文链接:https://www.haomeiwen.com/subject/iynfwctx.html