前言
在 Java 中,爲了更好的實踐分層思想,會把會區分 VO-展示層實體,DTO-數據傳輸層實體,DO-業務層主體,PO-持久層實體等等。儘管他們名字不同,功能也有所不同,但是對於同一個業務主體來說,其相關的實體屬性都是大同小異的,這個時候我們可以使用 get/set 方法來操作不過實在是一種下策。本文介紹 BeanUtils 工具類的使用,也是泛型實踐的一個例子。
BeanUtils 不光存在於 Spring
本文介紹的 BeanUtils 是取自 Spring-beans 包中的工具方法,但是並非只有 Spring 爲我們提供了這種功能的工具類
apache
apache 基金會也爲我們提供了具有類似功能的工具類。下面是 apache 提供的工具類的 Maven 依賴,其具體使用本文不會涉及,感興趣讀者可以自己研究一下。
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
cglib
cglib 也爲我們提供了類似的功能
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
BeanCopier beanCopier=
BeanCopier.create(source.getClass(), target.getClass(), false);
beanCopier.copy(source, target, null);
Spring 提供的 BeanUtils 用法舉例
Maven 依賴
本文 Spring 版本爲 4.3.0.RELEASE
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
工具類路徑
本文是 泛型使用的舉例,所以強烈建議讀者看一下源碼是怎麼實現的
org.springframework.beans.BeanUtils
源實體-一個模擬VO
/**
* 模擬來自前端的實體
* @author jecket
*
*/
public class SourceVO {
private String userName;
private String passWord;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Override
public String toString() {
return "SourceVO [userName=" + userName + ", passWord=" + passWord
+ "]";
}
}
目標實體-一個模擬DO
/**
* 模擬後臺對應數據庫的實體
* @author Jecket
*
*/
public class TargetEntity {
private String userName;
private int age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "TargetEntity [userName=" + userName + ", age=" + age + "]";
}
}
測試調用
測試了兩種調用方法,一種是所有同名屬性的值都會賦值給目標實體,一種是排除指定屬性剩餘的同名屬性纔會賦值給目標實體。
import org.junit.Test;
import org.springframework.beans.BeanUtils;
/**
* 測試 Spring 中 BeanUtils 中
* 具有相同屬性名稱的實體類間的屬性值賦值 方法
*
* 直白的說,就是免去了手動get,set 方法,
* 自動將源實體與目標實體同名屬性的值賦值給目標實體的同名屬性
* @author WuJieJecket
*
*/
public class SpringBeanUtilsTest {
@Test
public void testCopyProperties(){
//實例化 SourceVO 並賦值
SourceVO source=new SourceVO();
source.setUserName("jecket");
source.setPassWord("******");
//實例化接受數據的實體
TargetEntity target1=new TargetEntity();
TargetEntity target2=new TargetEntity();
//使用 Spring 中 BeanUtils.CopyProperties 方法將同名屬性值賦值給另一個實體
//但凡同名的都賦值
BeanUtils.copyProperties(source, target1);
System.out.println("方式一:同名屬性全部賦值,source賦值給target1");
System.out.println("source:"+source.toString());
System.out.println("target1:"+target1.toString());
//指定某些屬性不賦值,其餘但凡同名的都賦值
BeanUtils.copyProperties(source, target2,null,"userName","passWord");
System.out.println("方式二:排除 userName,passWord 屬性,其餘同名屬性全部賦值,source賦值給target2");
System.out.println("source:"+source.toString());
System.out.println("target2:"+target2.toString());
}
測試方法運行結果
方式一:同名屬性全部賦值,source賦值給target1
source:SourceVO [userName=jecket, passWord=******]
target1:TargetEntity [userName=jecket, age=0]
方式二:排除 userName,passWord 屬性,其餘同名屬性全部賦值,source賦值給target2
source:SourceVO [userName=jecket, passWord=******]
target2:TargetEntity [userName=null, age=0]