[JAVA/Spring] BeanUtils 관련
Development/Spring

[JAVA/Spring] BeanUtils 관련

반응형

Spring을 사용하다가, 은근히 종종 Class간 property를 복사해야 할 경우가 있다.



예를 들어, 위와 같은 클래스가 2개가 있다고 치자.


이 때 DB에서 조회한 Person1과 Person2가 있는데, 종종 어떠한 이유로 인하여 이 property를 서로 복사하거나 하는 작업을 해야할 때가 있다.


그럴때마다 원시적인 방법은 이를 그냥 set... set... 하면서 복사하는 방법이 있겠다(매우 비효율적이고 쓸데없이 코드 길이만 길어짐 & 가독성 최악)




@Data
@AllArgsConstructor
@NoArgsConstructor
class Person {
    private String name;
    private Integer id;
    private String address;
    private String phone;
}

        Person person1 = new Person("gompang", 1, "Seoul", "010-1234-1234");
        Person person2 = new Person("fungi", 2, "Incheon", "010-1234-1234");

        person2.setName(person1.getName());
        person2.setAddress(person1.getAddress());
        person2.setId(person1.getId());
        person2.setPhone(person1.getPhone());


물론 동작은 된다.


다만, 만약 접근해야 할 property가 수십, 수백개가 되는 상황에서라면.. 과연 어떻게 접근을 해야 할까?


이 각각의 property를 직접 복사하는 작업을 한다는 것은 정말 멍청한짓이 아닐 수 없다.


그래서 소개하고자 하는 방법은 Spring에서 제공하는 BeanUtils[각주:1] 를 사용하는 방법이 있겠다.


일단 이 유틸성 클래스의 소개를 보면


Static convenience methods for JavaBeans: for instantiating beans, checking bean property types, copying bean properties, etc.

Mainly for use within the framework, but to some degree also useful for application classes.


라고 설명이 되어 있다.


여기서 copying bean properties를 알아보자



    public static void copyProperties(Object source, Object target) throws BeansException {
        copyProperties(source, target, (Class)null, (String[])null);
    }


간단하게 위와 같은 메서드인데, 호출할 때 "원본 클래스", "대상 클래스" 를 지정하게 되면 해당 property가 복사되게 된다.


근데 아까부터 왜 계속 그냥 다른 클래스를 그대로 사용하면 되지, 왜 property를 복사하나요? 라는 질문이 들 수 있을것 같은데


실제로 각종 여러 클래스들의 값을 가지고 비지니스 로직을 짜다 보면 변경되어서는 안될 경우(collection에 들어가있는 값을 덮어쓰게 되면 문제가 발생할 수 있다) 나, 필요한 property만 복사하여 쓰고 싶은 경우(1-2개는 상관이 없으나 다수의 property를 복사하고자 할 때) 등 종종 필요한 케이스가 생긴다. 



그래서 위의 보기 안좋은 코드를 아래와 같이 변경할 수 있다



        // before
        person2.setName(person1.getName());
        person2.setAddress(person1.getAddress());
        person2.setId(person1.getId());
        person2.setPhone(person1.getPhone());

        // after
        BeanUtils.copyProperties(person1, person2);


static 메서드 하나만 호출해도 위와 같은 기능을 간단하게 사용할 수 있다.


그리고, 위와 같이 사용하게 되면 모든 property가 다 복사가 되게 되므로 문제가 될 수 있다(모든 값이 바뀌므로 바뀌지 않아야 할 데이터 또한 바뀌게 된다.)


이럴때는 ignore를 할 property를 지정해줌으로써 이를 방지할 수 있다.

 


BeanUtils.copyProperties(person1, person2, "name", "phone");


위와 같이 사용하게 되면 property를 복사하는데 "name" 과 "phone" 의 property는 복사하지 않는다.


dynamic String array로 전달을 받게 되므로, n개의 property를 명시해서 호출할 수 있다.


사실 BeanUtils 는 이런 목적 외에도 여러가지 기능을 더 가지고 있는데, 실제로 사용할법한 유용한 기능을 소개해보고자 한다.


Reflection을 사용한다고 했을 때, BeanUtils는 매우 유용한 라이브러리가 될 수 있을듯 하다


메서드를 찾는 메서드(?), - findMethod

정의된 메서드를 가져오는 메서드 - findDeclaredMethod

최우선 생성자를 가져오는 메서드 - findPrimaryConstructor


... 등 reflection을 이용해서 object를 핸들링하는데 유용하게 쓰일 수 있다.

  1. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/BeanUtils.html [본문으로]
반응형

'Development > Spring' 카테고리의 다른 글

Spring Redis Template Transaction  (2) 2021.09.09
Spring RequestContextHolder  (8) 2020.07.05
Spring Password Encoder  (4) 2019.04.06
Dispatcher Servlet  (0) 2019.04.06
Spring Boot Prometheus Converter 406 Not Acceptable  (0) 2019.04.06