Java'da Özel Sınıf Eşleyici

Feb 16 2023
Bu yazıda, MapStruct gibi üçüncü taraf kitaplıkları kullanmadan Java'da özel bir mapper util sınıfının nasıl uygulanacağını açıklayacağım. Arkadaşlar öncelikle Java programlama dili ve Java Reflection API hakkında temel bilgiye sahip olmalısınız.

Bu yazıda, MapStruct gibi üçüncü taraf kitaplıkları kullanmadan Java'da özel bir mapper util sınıfının nasıl uygulanacağını açıklayacağım.

Arkadaşlar öncelikle Java programlama dili ve Java Reflection API hakkında temel bilgiye sahip olmalısınız.

Hadi başlayalım.

public static <O, Target> O map(Object instance, Class<Target> targetClass) {
        if (instance.getClass().isPrimitive() || targetClass.isPrimitive()) {
            throw new RuntimeException("Provide a non primitive class");
        }

        if (instance.getClass().isInterface() || targetClass.isInterface()) {
            throw new RuntimeException("Provide a non interface class");
        }

        if (instance.getClass().isEnum() || targetClass.isEnum()) {
            throw new RuntimeException("Provide a non enum class");
        }

        if (Modifier.isAbstract(instance.getClass().getModifiers()) || Modifier.isAbstract(targetClass.getModifiers())) {
            throw new RuntimeException("Provide a non abstract class");
        }

        return doMap(instance, instance.getClass(), targetClass);
    }

@SneakyThrows
private static <O, Source, Target> O doMap(Object sourceInstance, Class<Source> sourceClass, Class<Target> targetClass) {
    Set<Field> declaredSourceFields = findAllFields(sourceClass);
    Set<Field> declaredTargetFields = findAllFields(targetClass);

    Object targetInstance = targetClass.getDeclaredConstructor().newInstance();

    for (Field field : declaredTargetFields) {
        Field sourceField = findSourceField(field, declaredSourceFields);
        if (sourceField != null) {
            field.setAccessible(true);
            field.set(targetInstance, sourceField.get(sourceInstance));
        }
    }
    return (O) targetInstance;
}

public static Set<Field> findAllFields(Class<?> inputClass) {
        Set<Field> allFields = new HashSet<>();

        if (inputClass == null) {
            return allFields;
        }

        Field[] fields = inputClass.getDeclaredFields();
        allFields.addAll(Set.of(fields));
        allFields.addAll(findAllFields(inputClass.getSuperclass()));
        return allFields;
}

private static Field findSourceField(Field targetField, Set<Field> declaredSourceFields) {
    for (Field field : declaredSourceFields) {
        field.setAccessible(true);
        String sourceFieldName = field.getName();
        if (sourceFieldName.equals(targetField.getName()) &&
                field.getType().equals(targetField.getType())) {
            return field;
        }
    }
    return null;
}

Örnekler:

@Setter
@Getter
public class SourceClass {
    String surname;
    Integer age;
    private String name;

    @Override
    public String toString() {
        return "SourceClass{" +
                "surname='" + surname + '\'' +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
@Setter
@Getter
public class TargetClass {
    Integer age;
    private String name;

    @Override
    public String toString() {
        return "TargetClass{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
public static void main(String[] args) {
        SourceClass sourceInstance = new SourceClass();
        sourceInstance.setAge(27);
        sourceInstance.setName("Java");
        sourceInstance.setSurname("Reflection");

        TargetClass targetInstance = CustomMapper.map(sourceInstance, TargetClass.class);
        System.out.println(targetInstance);
}

Soyadı, hedef sınıfta bulunmadığından çıktıda yok. Dolayısıyla, harita yöntemi bu alanı yok sayar.

Sonuç:
Java'da yazılmış kitaplıkların, çerçevelerin ve id'lerin çoğu Java Reflection API'den yararlanır. Ancak bu API, her işlem için güvenlik izinlerini kontrol ettiği için biraz yavaştır. Daha iyi performans için bu bağlantıdan Java Yöntemi Kollarını kontrol edebilirsiniz.https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.html.

Okuduğunuz için teşekkürler.
Saygılarımla