使用自定义注解:实现两个对象间,不同属性名之间的属性值复制

直接上代码:自定义注解、对象准备(源对象、目标对象)

自定义注解


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

import static java.lang.annotation.ElementType.FIELD;

@Target({FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CopyAnnotation {
    String value();
    Class type();
}

一、源对象


public class Resource {
    @CopyAnnotation(value = "name",type = Target.class)
    private String names;
    @CopyAnnotation(value = "age",type = Target.class)
    private int ages;
    @CopyAnnotation(value = "object", type = Target.class)
    private Object objects;

    public Resource(String names,int ages,Object objects){
        this.names = names;
        this.ages = ages;
        this.objects = objects;
    }
    public Resource(int ages,Object objects){
        this.ages = ages;
        this.objects = objects;
    }
    public Resource(){

    }
    public String getNames() {
        return names;
    }

    public void setNames(String names) {
        this.names = names;
    }

    public int getAges() {
        return ages;
    }

    public void setAges(int ages) {
        this.ages = ages;
    }

    public Object getObjects() {
        return objects;
    }

    public void setObjects(Object objects) {
        this.objects = objects;
    }
}

二、目标对象


public class Target {
    private int age;
    private String name;
    private Object object;
    public Target(String name,int age){
        this.name = name;
        this.age = age;
    }
    public Target(){

    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

三、属性复制工具类



import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 对象属性复制类
 * 将源对象中的属性值复制到目标对象中去
 * 如果源对象和目标对象相同的业务字段,属性名不相同。可以采用在源对象属性上加注解的方式,构建映射关系
 */
public class CopyUtil {
    private static Class myAnnotation = CopyAnnotation.class;

    /**
     * 对象属性赋值方法
     * 将 V 中的属性值,按照属性名的对应关系,复制到 K 中去
     * @param k   K 目标类
     * @param v   V 源对象
     * @param <K> 泛型
     * @param <V> 泛型
     */
    public static <K, V> void copy(K k, V v) {
        // 1.通过反射获取到b的属性值列表
        Field[] fields = v.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                // 1.获取属性名到源对象中的属性值(getter方式)
                Object value = getFieldValueByName(field.getName(), v);
                // 2.如果属性值为null,跳过该属性复制
                if (value == null) {
                    continue;
                }
                // 3.获取属性CopyAnnotation注解(自定义)的value值(对应的是目标对象的属性名)
                //    没有自定义注解,或者自定义注解没有对value属性赋值:使用原有的属性名
                String annotationName = getMyAnnotationValue(field);
                // 4.使用setter的方式将值复制到目标对象
                setTargetFieldValueByNameAndValue(k, annotationName, field.getType(), value);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println("====================对象属性赋值完成====================");
    }

    /**
     * 根据属性名,对象获取对象的属性值
     *
     * @param name 属性名
     * @param v    对象
     * @param <V>  泛型方法
     * @return Object 属性值
     * @throws IllegalAccessException    IllegalAccessException
     * @throws NoSuchMethodException     NoSuchMethodException
     * @throws InvocationTargetException InvocationTargetException
     */
    private static <V> Object getFieldValueByName(String name, V v)
            throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        String firstLetter = name.substring(0, 1).toUpperCase();
        String getter = "get" + firstLetter + name.substring(1);
        Method method = v.getClass().getMethod(getter, new Class[]{});
        return method.invoke(v, new Class[]{});
    }

    /**
     * 根据对象、属性名、参数类型、参数值
     * 使用反射调用setter进行对象属性的赋值操作
     *
     * @param k              对象
     * @param name           属性名
     * @param parameterClass 参数类型
     * @param value          参数值
     * @param <K>            泛型
     * @throws NoSuchMethodException     NoSuchMethodException
     * @throws InvocationTargetException InvocationTargetException
     * @throws IllegalAccessException    IllegalAccessException
     */
    private static <K> void setTargetFieldValueByNameAndValue(K k, String fieldName, Class parameterClass, Object value)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String firstLetter = fieldName.substring(0, 1).toUpperCase();
        String setter = "set" + firstLetter + fieldName.substring(1);
        Method method;
        method = k.getClass().getMethod(setter, new Class[]{parameterClass});
        method.invoke(k, value);
    }

    /**
     * 获取属性上自定义注解的value值
     *
     * @param field Field
     * @return String
     */
    private static String getMyAnnotationValue(Field field) {
        CopyAnnotation annotation = (CopyAnnotation) field.getAnnotation(myAnnotation);
        if (annotation == null || annotation.value() == null) {
            return field.getName();
        }
        return annotation.value();
    }
}

四、测试类

/**
 * @ClassName Test
 * @Deacription TODO
 * @Author gongyunlong
 * @Date 2019/11/4 16:40
 * @Version 1.0
 **/
public class Test {

    public static void main(String[] args) {
        Resource resource = new Resource("要复制的属性",1,new Object());
//        Resource resource = new Resource(1,new Object());
        Target target = new Target();
        CopyUtil.copy(target,resource);
    }
}

五、尚未解决的问题

尚未解决复杂对象间的属性复制操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章