Simple and practical object transformation replication tool (continued 2)

Keywords: Programming

Previous link:

Just in a flash of fancy, I think that a source object may be copied to multiple target objects, and the fields that these target objects need to copy are not the same. So I opened the editor for further improvement.

First, ideas

This function is actually very simple, and the idea is basically the same as the previous @ IgnoreFields annotation. It is to add an annotation, and then judge whether to copy this field according to the annotation during conversion.

Two, implementation

Don't talk too much, just start to realize the function.

The first step is to create a new annotation to state that the field does not need to be copied in those classes.

public @interface IgnoreClass {
    Class<?>[] value() default {};

The second step is to modify the transfean method of ObjectTransUtil to add judgment on the new annotation. Just get the IgnoreClass annotation of the Field after processing the Field circularly. If the annotation is empty or the Class array in the annotation does not contain the target Class, we will copy the object. The modified transBean method is as follows:

    public static <K extends Serializable, V> V transBean(K k, Class<V> vClass) throws IllegalAccessException, InvocationTargetException {
        Class<?> kClass = k.getClass();
        List<Field> fieldList = Arrays.asList(kClass.getDeclaredFields());
        // Check whether beantran annotation is annotated, obsolete
        fieldList = checkBeanTrans(kClass, fieldList);
        if (kClass.isAnnotationPresent(IgnoreFields.class)) {
            IgnoreFields ignoreFields = kClass.getAnnotation(IgnoreFields.class);
            List<String> ignoreFiledList = Arrays.asList(ignoreFields.value());
            if (CollectionUtils.isNotEmpty(ignoreFiledList)) {
                fieldList =
                        .filter(field -> !ignoreFiledList.contains(field.getName()))
        //Loop the variable to be converted, and get the result through reflection conversion.
        V v;
        try {
            v = vClass.getDeclaredConstructor().newInstance();
        } catch (InstantiationException e) {
            throw new ObjectTransException("Cannot instantiate abstract class or interface.", e);
        } catch (NoSuchMethodException e) {
            throw new ObjectTransException(vClass.getName() + "There is no default construction method.", e);
        for (Field field : fieldList) {
            String name = field.getName();
            TransTarget transTarget = field.getAnnotation(TransTarget.class);
            String s = transTarget != null ? transTarget.value() : name;
            IgnoreClass ignoreClass = field.getAnnotation(IgnoreClass.class);
            Class<?>[] classes = ignoreClass != null ? ignoreClass.value() : null;
            if (ArrayUtils.isEmpty(classes) ||
                    !Arrays.asList(classes).contains(vClass)) {
                Field targetField;
                try {
                    targetField = vClass.getDeclaredField(s);
                } catch (NoSuchFieldException e) {
                if (field.getType().equals(targetField.getType())) {
                    String sourceMethodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
                    String targetMethodName = "set" + s.substring(0, 1).toUpperCase() + s.substring(1);
                    Method sourceMethod;
                    Method targetMethod;
                    try {
                        sourceMethod = kClass.getDeclaredMethod(sourceMethodName);
                        targetMethod = vClass.getDeclaredMethod(targetMethodName, field.getType());
                    } catch (NoSuchMethodException e) {
                        throw new ObjectTransException("Unable to get the corresponding get/set Method.", e);
                    Object invoke = sourceMethod.invoke(k);
                    targetMethod.invoke(v, DeepCloneUtil.clone(invoke));
        return v;

At this point, this function is completed, quite simple. The old rule is to test:

public class Test {
    public static void main(String[] args) throws InvocationTargetException, NoSuchFieldException, IllegalAccessException {
        Source source = new Source();
        Target target = ObjectTransUtil.transBean(source, Target.class);
        Target2 target2 = ObjectTransUtil.transBean(source, Target2.class);


@IgnoreFields(value = "d")
class Source implements Serializable {
    Integer b;

class Target {
    Integer b;

class Target2 {
    Integer b;

The operation result is:

In terms of results, the effect is still achieved. As for whether there will be other problems, I will explore them slowly in my use.

Source code: Object conversion tools


Welcome to my personal official account, push the latest article.

Posted by Xyphon on Wed, 04 Mar 2020 20:57:35 -0800