Spring超詳細(xì)講解BeanUtils改造
1.基本原理
原理:http://www.dhdzp.com/article/252384.htm
淺拷貝:http://www.dhdzp.com/article/221283.htm
BeanUtils.copyProperties();確實(shí)為我們做了很多事情,雖然不能完美完成深拷貝,但是對(duì)于 po、vo、dto 的拷貝已經(jīng)足夠用了。但是其還是有一些不夠完美的地方。
不足幾點(diǎn)如下:
不能拷貝 list,而拷貝 list 的情況又大量存在,因此會(huì)有許多重復(fù)代碼。
for (S source : sources) {
T target = new T();
copyProperties(source, target);
list.add(target);
}
有一些簡(jiǎn)單的查詢,僅僅需要轉(zhuǎn)換一下 vo 也需要 new Vo()。
public Vo findById(Integer id) {
Vo vo = new Vo();
Po po = dao.findById(id);
copyProperties(po, vo);
return vo;
}
這種拷貝方式是沒有返回值的,jdk8 支持 stream() 操作之后,支持不是很友好,不方便 lambda 表達(dá)式的使用,因此我們決定通過集成 BeanUtils 類,自己造一個(gè)方便用的輪子。
2.使用
我們將新創(chuàng)建一個(gè)工具類 BeanConvertUtils,使用如下,當(dāng)我們要轉(zhuǎn)換 po、vo 時(shí),只需要:
// 使用前
public Vo findById(Integer id) {
Vo vo = new Vo();
Po po = dao.findById(id);
copyProperties(po, vo);
return vo;
}
// 使用后
public Vo findById(Integer id) {
return BeanConvertUtils.converTo(dao.findById(id), Vo::new);
}
// 使用后,通過lambda表達(dá)式特殊處理個(gè)別字段
public Vo findById(Integer id) {
return BeanConvertUtils.converTo(dao.findById(id), Vo::new,
(s, t) -> t.setName(s.getName))
);
}
當(dāng)我們要拷貝 list 的時(shí)候也很簡(jiǎn)單:
// 使用前
public List<Vo> findAll() {
List<Vo> vos = new ArrayList();
List<Po> pos = dao.findAll();
for (Po po : Pos) {
Vo vo = new Vo();
BeanUtis.copyProperties(po, vo);
vos.add(vo);
}
return vos;
}
// 使用后
public List<Vo> findAll() {
return BeanConvertUtils.converToList(dao.findAll(), Vo::new)
}
// 同樣支持自定義lambda
public List<Vo> findAll() {
return BeanConvertUtils.converToList(dao.findAll(), Vo::new,
(s, t) -> t.setName(s.getName))
)
}
工具代碼如下:
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
/**
* Spring-BeanUtils轉(zhuǎn)換對(duì)象工具封裝(淺拷貝)
*/
public class BeanConvertUtils extends BeanUtils {
/**
* 拷貝對(duì)象
* @param source
* @param targetSupplier
* @param <S>
* @param <T>
* @return
*/
public static <S, T> T convertTo(S source, Supplier<T> targetSupplier) {
return convertTo(source, targetSupplier, null);
}
/**
* 拷貝list
*
* @param sources
* @param targetSupplier
* @param <S>
* @param <T>
* @return
*/
public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier) {
return convertListTo(sources, targetSupplier, null);
}
/**
* 轉(zhuǎn)換對(duì)象
*
* @param source 源對(duì)象
* @param targetSupplier 目標(biāo)對(duì)象供應(yīng)方
* @param callBack 回調(diào)方法
* @param <S> 源對(duì)象類型
* @param <T> 目標(biāo)對(duì)象類型
* @return 目標(biāo)對(duì)象
*/
public static <S, T> T convertTo(S source, Supplier<T> targetSupplier, ConvertCallBack<S, T> callBack) {
if (null == source || null == targetSupplier) {
return null;
}
T target = targetSupplier.get();
copyProperties(source, target);
if (callBack != null) {
callBack.callBack(source, target);
}
return target;
}
/**
* 轉(zhuǎn)換對(duì)象
*
* @param sources 源對(duì)象list
* @param targetSupplier 目標(biāo)對(duì)象供應(yīng)方
* @param callBack 回調(diào)方法
* @param <S> 源對(duì)象類型
* @param <T> 目標(biāo)對(duì)象類型
* @return 目標(biāo)對(duì)象list
*/
public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier, ConvertCallBack<S, T> callBack) {
if (null == sources || null == targetSupplier) {
return null;
}
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T target = targetSupplier.get();
copyProperties(source, target);
if (callBack != null) {
callBack.callBack(source, target);
}
list.add(target);
}
return list;
}
/**
* 回調(diào)接口
*
* @param <S> 源對(duì)象類型
* @param <T> 目標(biāo)對(duì)象類型
*/
@FunctionalInterface
public interface ConvertCallBack<S, T> {
void callBack(S t, T s);
}
}
3.性能
由于只是 BeanUtils 的一個(gè)封裝,跟原來的代碼性能幾乎差不多,如果要說差一點(diǎn)也沒錯(cuò),畢竟多了一層函數(shù)堆棧的調(diào)用,但是基本可以忽略不計(jì)。主要的性能還是由 BeanUtils 決定。
4.提醒
不知道大家對(duì)這個(gè) BeanConvertUtils 工具類感覺怎么樣,自己在項(xiàng)目中倒是大量使用,也很方便。
但是有兩點(diǎn)要提醒:
- 此方法依舊不能解決深層次的深拷貝問題,詳細(xì)的可以 google 一下 BeanUtils 的深拷貝問題。
- 如果 source 或者 targetSupplier 只要有一個(gè)為 null,本工具類不像 BeanUtils 一樣拋出異常,而是返回 null,因?yàn)楣P者認(rèn)為調(diào)用方如果把 null 進(jìn)行準(zhǔn)換,那就是想轉(zhuǎn)換為 null,為不為空應(yīng)該由調(diào)用方自己負(fù)責(zé)。
到此這篇關(guān)于Spring超詳細(xì)講解BeanUtils改造的文章就介紹到這了,更多相關(guān)Spring BeanUtils內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用JDBC或MyBatis框架向Oracle中插入XMLType數(shù)據(jù)
XMLType是Oracle支持的一種基于XML格式存儲(chǔ)的數(shù)據(jù)類型,這里我們共同來探究Java使用JDBC或MyBatis框架向Oracle中插入XMLType數(shù)據(jù)的方法:2016-07-07
淺談mybatis返回單一對(duì)象或?qū)ο罅斜淼膯栴}
這篇文章主要介紹了淺談mybatis返回單一對(duì)象或?qū)ο罅斜淼膯栴},具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Intellij IDEA連接Navicat數(shù)據(jù)庫的方法
這篇文章主要介紹了Intellij IDEA連接Navicat數(shù)據(jù)庫的方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借價(jià)值,需要的朋友可以參考下2021-03-03
詳解Spring Security 中的四種權(quán)限控制方式
這篇文章主要介紹了詳解Spring Security 中的四種權(quán)限控制方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java 比較接口comparable與comparator區(qū)別解析
這篇文章主要介紹了Java 比較接口comparable與comparator區(qū)別解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
基于JavaBean編輯器讀取peroperties文件的實(shí)例
下面小編就為大家?guī)硪黄贘avaBean編輯器讀取peroperties文件的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10

