Custom Class Mapper ใน Java
Feb 16 2023
ในบทความนี้ ฉันจะอธิบายวิธีการใช้คลาส util ของ mapper แบบกำหนดเองใน Java โดยไม่ต้องใช้ไลบรารีของบุคคลที่สาม เช่น MapStruct ก่อนอื่น พวกคุณควรจะมีความรู้พื้นฐานเกี่ยวกับภาษาโปรแกรม Java และ Java Reflection API
ในบทความนี้ ฉันจะอธิบายวิธีการใช้คลาส util ของ mapper แบบกำหนดเองใน Java โดยไม่ต้องใช้ไลบรารีของบุคคลที่สาม เช่น MapStruct
ก่อนอื่น พวกคุณควรจะมีความรู้พื้นฐานเกี่ยวกับภาษาโปรแกรม Java และ Java Reflection API
เริ่มกันเลย.
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;
}
ตัวอย่าง:
@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);
}
ไม่มีนามสกุลในผลลัพธ์เนื่องจากไม่มีอยู่ในคลาสเป้าหมาย ดังนั้น map method จะละเว้นฟิลด์นี้
สรุป:
ไลบรารี กรอบงาน และ ides ส่วนใหญ่ที่เขียนด้วย Java ใช้ประโยชน์จาก Java Reflection API แต่ API นี้ค่อนข้างช้าเพราะตรวจสอบสิทธิ์การรักษาความปลอดภัยสำหรับการดำเนินการแต่ละครั้ง เพื่อประสิทธิภาพที่ดีขึ้น คุณสามารถตรวจสอบ Java Method Handles ได้จากลิงค์นี้https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.html.
ขอบคุณสำหรับการอ่าน.
ขอแสดงความนับถืออย่างสูง





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)