基于注解进行对象拷贝(一)

背景

做为一名CRUD boy,很是厌烦了Ctrl+C & Ctrl+V的方式进行开发。尤为是在Web类项目开发中,咱们常常会遇到PO(Persistent Object, 持久化对象),DTO(Data Transfer Object, 数据传输对象),VO(View Object, 视图对象)对象之间的转换,毕竟后端总不能把数据库原始数据直接丢给前端进行处理(估计会被🔪),返回一个合适的DTO给前端,是一个优秀CRUD工程师的自觉。前端

问题

一般咱们从数据库查询某个PO对象后,通过一番加工,将其某些属性拷贝给DTO对象或者VO对象返回到前端进行进一步处理或者直接展现。因此代码出现最多的语句就是这几种对象之间各类属性的相互赋值:java

  • 属性较多,手写比较繁琐
  • 增长冗余代码量,给后续维护带来没必要要的工做量
  • 因为赋值在代码中的位置比较分散,属性之间的对应关系难以进行维护
  • 为了便于语义化理解,DTO、VO以及PO对象中属性的名称可能不一样,也要能实现正确的拷贝
  • 在属性值类型不一样时,可以实现不一样类型对象间的转换
  • ...

已有方案

虽然已有对象拷贝的各类类库:BeanUtils,BeanCopier等,可是在使用上总不是那么顺手,咱们须要一种很是轻量级的对象拷贝方法,因而就有了借助于注解和反射进行对象拷贝的方法。git

注解方案

之因此采用注解方案有如下几点缘由:github

  • 注解能够实现对源数据无侵入性,不会涉及源数据的改动
  • 注解不会目标对象的原有逻辑
  • 易扩展,能够经过不断增长解析类的功能来扩展对象拷贝功能

特性

  • 经过注解中的name字段,能够实现不一样名称属性的拷贝
  • 经过注解中的methodClass、methodName、parameters字段能够实现不一样属性值之间的类型转换
  • 注解做用与单个属性上,按需取用便可,默认相同属性名称自动进行拷贝

注解代码

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface AliasField {
    /** * 可供拷贝的属性的名称,以注解中注册的名称优先,寻找名称对应的getter函数 * 第一个找到的getter函数即为源 */
    String[] name() default {};

    /** * 将源值转换为目标值的方法所在的类,默认为目标对象 */
    Class methodClass() default Class.class;

    /** * 将源值转换为目标值的方法名称 */
    String methodName() default "";

    /** * 将源值转换为目标值的方法须要的参数 */
    Class[] parameters() default {};
}
复制代码

DEMO

源对象
public class UserTable {
    public UserTable(long id, String des, String userId){
        this.id = id;
        this.des = des;
        this.userId = userId;
    }

    private long id;

    private String des;

    private String userId;

    public long getId(){
        return id;
    }

    public String getDes(){
        return des;
    }

    public String getUserId(){
        return userId;
    }
}
复制代码
目标对象
public class UserProtocol {
    private long id;

    public void setId(long id){
        this.id = id;
    }

    @AliasField(name={"des"})
    private String content;
    public void setContent(String content){
        this.content = content;
    }

    @AliasField(name={"userId"}, methodName = "String2Int", parameters = {String.class})
    private long selfId;
    public void setSelfId(long userId){
        this.selfId = userId;
    }

    public static int String2Int(String userId){
        return Integer.valueOf(userId);
    }

    @Override
    public boolean equals(Object object){
        if(object == null){
            return false;
        }
        else if(object == this){
            return true;
        }
        else if(object instanceof UserTable){
            UserTable target = (UserTable)object;
            return id == target.getId() && content.equals(target.getDes()) && selfId == Integer.valueOf(target.getUserId());
        }
        else if(object instanceof UserProtocol){
            UserProtocol target = (UserProtocol)object;
            return id == target.id && content.equals(target.content) && selfId == target.selfId;
        }
        else {
            return false;
        }
    }

    @Override
    public String toString() {
        return id+"-"+content+"-"+selfId;
    }
}
复制代码
对象拷贝

经过一个函数简单调用便可实现对象拷贝数据库

userTable = new UserTable(2019, "I am bast!", "2020");
UserProtocol userProtocol = new UserProtocol();
Convert.convert(userProtocol, userTable);
复制代码

更多使用方法请见代码中的单元测试案例

相关文章
相关标签/搜索