Bean Copy:BeanUtils copyProperties VS PropertyUtils copyProperties

Version-info: BeanUtils 1.7.0

bean을 전혀 다른 bean(상속받은 것도 아니고 같은 패키지도 아닌 전혀 상관없는 bean)으로 복사를 하고 싶을 때가 있다. 일일이 복사를 하자니 노가다이고, 상속 같은 방법을 써보고도 싶지만 return type이 서로 다른 같은 이름이 있으면 상속이 안되는 등 귀찮은 작업이 될 여지가 많다. 이럴 때 Apache commonsBeanUtils를 사용한다.

이 패키지를 쓸 때, bean을 복사하는 방법에는 두가지 방법이 있다.

  1. PropertyUtils를 사용하는 방법과
  2. BeanUtils를 사용하는 방법

두 객체 모드 copyProperties 함수가 있으나 동작방식은 다르다.

공통적으로

같은 이름의 property에 대해서만 복사가 이루어진다.

당연하게도 destination에 setter가 없거나, original에서 getter가 없는 property에 대해서는 복사가 이루어지지 않는다.

1.의 경우

original bean과 destination bean의 모든 property는 동일한 객체여야 한다. 객체가 틀릴 경우 IllegalArgumentException이 발생한다.

즉, 두개의 bean이 같은 property에 대해서는 객채가 일치해야 한다.

또한 destination bean의 “age”라는 property의 setter가 int 형으로 parameter를 받고, original bean에서 “age”의 getter가 값을 Integer 객체로 return할 때, 만약 orignal bean의 “age”가 null이어도 IllegalArgumentException이 발생한다. 왜냐하면 destination의 setter function의 primitive type paramter가 null로 들어가기 때문이다.

따라서, 같은 property가 original bean은 primitive object, destination bean은 primitive type일 경우 original bean의 해당 property가 null이 된 상태에서 PropertyUtils.copyProperties 함수를 사용하지 않도록 주의해야 한다.

2. 의 경우

original bean의 getter가 return하는 객체와 destination bean의 setter는 parameter 객체는 동일할 필요가 없다. BeanUtils에서 적절하게 property type의 변환을 해주며, PropertyUtils에서 설명한 primitive type에 사용에 따른 Exception도 적절하게 처리해준다.

BeanUtils는 기본적으로 ConvertUtilsBean 에서 설정된 default 값을 가지고 변환이 이루어진다. 부적절한 변환일 경우 default 값으로 변환되며, String이 char로 변환될 경우 첫글자로 변환되는 식이다.

이러한 변환 과정이 구현에 따라 바뀔 필요가 발생할 떄도 있는데, 이는 ConvertUtilsBean으로 해결이 가능하다. ConvertUtilsBean에서 구현이 바뀌어야 할 type을 deregister 함수로 빼고 난 뒤, 새롭게 정의한 Converter를 해당 type으로 register함수를 이용하여 등록해주면 된다.

import org.apache.commons.beanutils.*;
public class Test {
	public static void main(String[] args){
		...
		ConvertUtilsBean cub = new ConvertUtilsBean();
		cub.deregister(Integer.class);
		cub.register(new IntConv(), Integer.class);
		cub.register(new IntConv(), Integer.TYPE);

		BeanUtilsBean bub = new BeanUtilsBean(cub, new PropertyUtilsBean());

		bub.copyProperties(destination, original);
		...
	}
}

class IntConv implements Converter{
	//	implemented method
	public Object convert(Class type, Object value){
		if(value == null){
			return 0;
		}else{
			if(value instanceof Integer){
				return value.intValue();
			}else if(value instanceof String){
				return -1;
			}else if(value instanceof AnotherObject){
				return someValue;
			}else...
		}
	}
}

여기서 중요한 것은 String -> Integer로 변환되는 것을 새롭게 정의하고 싶다면, String.class 에 정의된 Converter를 바꾸는게 아니고 Integer.class에 정의 된 Converter를 바꿔야 한다는 것이다. convert함수의 구현을 잘 보면 알겠지만 original의 다양한 객체에 대해서 대응하고 return 값은 int로 바꾸고 있다.

BeanUtilsBean의 생성자 parameter에 포함된 PropertyUtilsBean은 어따 써먹는지 잘 모르겠다. -_-

여기서 또 한발짝 나가면 특정 property만 변경해서 복사하고 싶을 때가 있다. 예를 들어 다른 int 속성은 안바꾸고 1980년을 29세로 바꾸고 싶은 경우. 이럴 때 내가 낸 해답은 describe함수를 쓰는 것이다.

이 역시 BeanUtils와 PropertyUtils 모두 가지고 있는 함수이지만 역시 동작 방식은 다르다. 다음 포스팅은 이에 대해서 다룬다.

Advertisement

~ by insoul2u on April 7, 2008.

One Response to “Bean Copy:BeanUtils copyProperties VS PropertyUtils copyProperties”

  1. [...] Conversion:BeanUtils describe VS. PropertyUtils describe Bean Copy 포스트의 말미에서 얘기했듯이 특정 property를 변환하여 bean을 복사하는 [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.