利用泛型、自定义注解和反射实现PO与VO的快捷转换

     咱们不少状况下,前台须要从新定义一个ValueObject即VO对象来转换后台的实体对象PO。主要的做用有隐藏不暴露PO的一些属性,前台只需关心展现视图须要的部分属性便可。VO通常要进行传输,所以咱们定义VO通常会实现序列化,以提升对象的传输效率。PO与VO的属性转换,传统比较笨拙的办法固然就是本身手动写一个又一个的getter和setter。相对比较繁琐吧!java

      固然开源的apache common  util包下有个BeanUtils工具类也能够方便两个实体之间的通用快速转换,但我这里要讲的不是这个。这里要说的是,咱们自定义本身的注解,而后经过指定须要绑定的转换的属性,利用Java的反射机制,实现一种相对比较通用的PO与VO的转换方式。apache

首先,咱们来定义两个注解,主要的思路和做用是标记VO与PO类的绑定,和VO定义的属性中与PO对应的属性的绑定。好了,直接来看看下面自定义注解的实现代码:app

BinEntity.javaide

package org.haycco;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 声明须要绑定的实体注解
 * 
 * @author haycco
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface BindEntity {
    
    Class<?> value();

}

BindFieldName.java工具

package org.haycco;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 声明须要绑定的属性名注解
 * 
 * @author haycco
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindFieldName {
    
    String value();

}

  好了,咱们以上的代码定义了两个注解,接下来写两个简单的PO和VO类。代码以下所示:测试

UserPO.javathis

/**
 * CopyRright (C) 2013:   haycco All Rights Reserved.
 */
package org.haycco;

/**
 * @author haycco
 */
public class UserPO {
    
    private long id;
    private String account;
    private String name;
    private String password;
    
    public UserPO(long id, String account, String name, String password) {
        this.id = id;
        this.account = account;
        this.name = name;
        this.password = password;
    }

    public long getId() {
        return id;
    }

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

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

UserVO.java对象

/**
 * CopyRright (C) 2013:   haycco All Rights Reserved.
 */
package org.haycco;

import java.io.Serializable;

/**
 * @author haycco
 */
@BindEntity(UserPO.class)
public class UserVO implements Serializable {

    private static final long serialVersionUID = -1197093269635543264L;

    @BindFieldName("id")
    private Integer id;

    @BindFieldName("account")
    private String userName;

    @BindFieldName("name")
    private String name;

    @BindFieldName("password")
    private String password;

    public Integer getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    
    @Override
    public String toString() {
        return "id=" + id + ", name=" + name + ", userName=" + userName + ", password=" + password;
    }

}

  那到接下来看看如何利用Java的反射机制来调用setter和getter方法的具体实现代码:blog

/**
     * 获取get方法
     * 
     * @param objectClass
     * @param fieldName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Method getGetMethod(Class objectClass, String fieldName) {
        StringBuffer sb = new StringBuffer();
        sb.append("get");
        sb.append(fieldName.substring(0, 1).toUpperCase());
        sb.append(fieldName.substring(1));
        try {
            return objectClass.getMethod(sb.toString());
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 获取set方法
     * 
     * @param objectClass
     * @param fieldName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Method getSetMethod(Class objectClass, String fieldName) {
        try {
            Class[] parameterTypes = new Class[1];
            Field field = objectClass.getDeclaredField(fieldName);
            parameterTypes[0] = field.getType();
            StringBuffer sb = new StringBuffer();
            sb.append("set");
            sb.append(fieldName.substring(0, 1).toUpperCase());
            sb.append(fieldName.substring(1));
            Method method = objectClass.getMethod(sb.toString(), parameterTypes);
            return method;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 执行set方法
     * 
     * @param o
     * @param fieldName
     * @param value
     */
    public static void invokeSet(Object o, String fieldName, Object value) {
        Method method = getSetMethod(o.getClass(), fieldName);
        try {
            method.invoke(o, new Object[] { value });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行get方法
     * 
     * @param o
     * @param fieldName
     * @return
     */
    public static Object invokeGet(Object o, String fieldName) {
        Method method = getGetMethod(o.getClass(), fieldName);
        try {
            return method.invoke(o, new Object[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

  此上的代码片段是比较通用的调用setter和getter的方式。那接下来咱们就要定义本身的VO转换器了,为了进一步抽象化通用,这里咱们经过泛型的方式来实现,废话少说吧,直接上全部的VO转换器的代码了。get

ValueObjectTransfer.java

/**
 * CopyRright (C) 2013:   haycco All Rights Reserved.
 */
package org.haycco;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * VO转换器
 * 
 * @author haycco
 */
@SuppressWarnings("rawtypes")
public class ValueObjectTransfer<VO, PO> {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        List<UserPO> poList = new ArrayList<UserPO>();
        poList.add(new UserPO(1, "first", "Haycco", "1234"));
        poList.add(new UserPO(2, "second", "Haycco", "2345"));

        ValueObjectTransfer<UserVO, UserPO> transfer = new ValueObjectTransfer<UserVO, UserPO>();
        List<UserVO> voList = transfer.cast(poList, UserVO.class);
        int j = 0;
        for (UserVO vo : voList) {
            System.out.println("*****************************************ValueObject: " + ++j);
            System.out.println("UserVO: " + vo.toString());
        }
    }

    /**
     * 转换PO列表
     * 
     * @param poList 须要转换的PO列表
     * @param voClass 须要转换后的VO类
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     */
    public List<VO> cast(List<PO> poList, Class<VO> voClass) throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        List<VO> voList = new ArrayList<VO>();
        for (PO po : poList) {
            VO vo = this.cast(po, voClass);
            voList.add(vo);
        }
        return voList;
    }

    /**
     * PO->VO
     * @param po 须要转换的PO
     * @param voClass 须要转换后的VO类
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     */
    @SuppressWarnings("unchecked")
    public VO cast(PO po, Class<VO> voClass) throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        // 判断须要转换的PO是否跟VO所绑定的PO一致
        if (!voClass.isAnnotationPresent(BindEntity.class)) {
            //须要转换的PO与VO所绑定的PO不一致
            return null;
        } 
        // 反射获取VO的实例
        VO vo = (VO) ClassLoader.getSystemClassLoader().loadClass(voClass.getName()).newInstance();
        // 遍历VO全部声明的属性
        for (Field field : voClass.getDeclaredFields()) {
             Class type = field.getType();
            String name = field.getName();
            // 判断是否包含声明为BindFieldName注解的属性
            if (field.isAnnotationPresent(BindFieldName.class)) {
                BindFieldName bindFieldName = field.getAnnotation(BindFieldName.class);
                // 反射调用绑定的PO属性的get方法进行取值
                Object value = invokeGet(po, bindFieldName.value());
                // 反射调用执行该VO属性的set方法设置值
                //TODO 须要完善各类属性类型的转换
                if(type.isInstance(value)) {
                    invokeSet(vo, name, value);
                }
                
            }

        }
        return vo;
    }

    /**
     * 获取get方法
     * 
     * @param objectClass
     * @param fieldName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Method getGetMethod(Class objectClass, String fieldName) {
        StringBuffer sb = new StringBuffer();
        sb.append("get");
        sb.append(fieldName.substring(0, 1).toUpperCase());
        sb.append(fieldName.substring(1));
        try {
            return objectClass.getMethod(sb.toString());
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 获取set方法
     * 
     * @param objectClass
     * @param fieldName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Method getSetMethod(Class objectClass, String fieldName) {
        try {
            Class[] parameterTypes = new Class[1];
            Field field = objectClass.getDeclaredField(fieldName);
            parameterTypes[0] = field.getType();
            StringBuffer sb = new StringBuffer();
            sb.append("set");
            sb.append(fieldName.substring(0, 1).toUpperCase());
            sb.append(fieldName.substring(1));
            Method method = objectClass.getMethod(sb.toString(), parameterTypes);
            return method;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 执行set方法
     * 
     * @param o
     * @param fieldName
     * @param value
     */
    public static void invokeSet(Object o, String fieldName, Object value) {
        Method method = getSetMethod(o.getClass(), fieldName);
        try {
            method.invoke(o, new Object[] { value });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行get方法
     * 
     * @param o
     * @param fieldName
     * @return
     */
    public static Object invokeGet(Object o, String fieldName) {
        Method method = getGetMethod(o.getClass(), fieldName);
        try {
            return method.invoke(o, new Object[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

  以上就是全部实现代码,利用Java的泛型、注解和反射的方式。须要测试的童鞋,只需执行ValueObjectTransfer.java的main方法便可。这样的方式,在通用性来讲仍是比较灵活的,在VO对象用@BindEntity注解绑定对应的PO类,须要自动赋值的VO属性也只需加上@BindFieldName注解进行标记就能够了,但目前上面的代码只是作到同类型属性的setter和getter。还有待完善各类属性类型值的转换,因为须要浩大的if else代码,各位有兴趣的童鞋,本身去完善吧。

相关文章
相关标签/搜索