使用自定義註解:實現兩個對象間,不同屬性名之間的屬性值複製

直接上代碼:自定義註解、對象準備(源對象、目標對象)

自定義註解


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);
    }
}

五、尚未解決的問題

尚未解決複雜對象間的屬性複製操作

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