1. 程式人生 > 其它 >BeanUtils.copyProperties原始碼的修改

BeanUtils.copyProperties原始碼的修改

昨天隨便說一下pojo和vo和dto的關係給大家2個需求 昨天的部落格的地址 https://mp.weixin.qq.com/s?__biz=MzA4MTAwMzA1Mw==&mid=2247484844&idx=1&sn=b950db1607efa078ccc41af61d885dc4&chksm=9f9ad2eea8ed5bf800d2a6d56eddebb33487f1db0741b6a71c0ea262db79480f7fbcb8119ebb&token=722122288&lang=zh_CN#rd 需求

假設是從A複製到B:
需求1:如果B中某欄位有值(不為null),則該欄位不復制;
也就是B中該欄位沒值時,才進行復制,適合於對B進行補充值的情況。
需求2:如果A中某欄位沒值(為null),則該欄位不復制
也就是不要把null複製到B當中

先解決第一個需求

求1:如果B中某欄位有值(不為null),則該欄位不復制; 也就是B中該欄位沒值時,才進行復制,適合於對B進行補充值的情況。

解決方案

這裡我使用的是自定義註解當自定義註解放在那個欄位上面就不進行復制 重寫這個複製的原始碼

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})//
//1.CONSTRUCTOR:用於描述構造器
//2.FIELD:用於描述域
//3.LOCAL_VARIABLE:用於描述區域性變數
//4.METHOD:用於描述方法//
//6.PARAMETER:用於描述引數//
7.TYPE:用於描述類、介面(包括註解型別)或enum宣告
//ElementType.FIELD只能用在欄位上
@Documented
@Component
public@interfacejudge{
}

B

@Data

publicclassDepartmentimplementsSerializable{
privateIntegerdepartmentid;
@judge
Stringdepartmentname;
privateIntegermanagerid;
privateStringhh;
}

A

@Data

@NoArgsConstructor
publicclassDepartmentidDto{
privateIntegerdepartmentid;
privateStringdepartmentname;
privateStringhh;

}

main

publicclassYY{
publicstaticvoidmain(String[]args)throwsInvocationTargetException,IllegalAccessException{
DepartmentidDtodepartment=newDepartmentidDto();
department.setDepartmentid(1);
department.setHh("4444444");
department.setDepartmentname("2222222222222");
Departmentdepartmentid=newDepartment();
//
departmentid.setDepartmentname("3333333333333333333");
departmentid.setHh("12314");

//前面是dtoa後面是pojob
BeanUtilsVo.copyProperties(department,departmentid);
System.out.println(departmentid.toString());


}
}

可以看到a向b複製 欄位departmentname的值在b是3333333333333333333 a的值是2222222在b上加上自定義註解

重寫方法

publicabstractclassBeanUtilsVo{
/**使用的方法為copyProperties(Objectsource,Objecttarget)**/
publicstaticvoidcopyProperties(Objectsource,Objecttarget)throwsBeansException{
//複製的被複制的
copyProperties(source,target,(Class)null,(String[])null);
}
privatestaticvoidcopyProperties(Objectsource,Objecttarget,@NullableClass<?>editable,@NullableString...ignoreProperties)throwsBeansException{
Assert.notNull(source,"Sourcemustnotbenull");
/**
//物件為空則丟擲異常IllegalArgumentException
publicstaticvoidnotNull(@NullableObjectobject,Stringmessage){
if(object==null){
thrownewIllegalArgumentException(message);
}
}
**/
Assert.notNull(target,"Targetmustnotbenull");

Class<?>actualEditable=target.getClass();
if(editable!=null){
if(!editable.isInstance(target)){
thrownewIllegalArgumentException("Targetclass["+target.getClass().getName()+"]notassignabletoEditableclass["+editable.getName()+"]");
}

actualEditable=editable;
}
//獲取PropertyDescriptor(屬性描述器)陣列,getPropertyDescriptors具體內容看下方
PropertyDescriptor[]targetPds=getPropertyDescriptors(actualEditable);
List<String>ignoreList=ignoreProperties!=null?Arrays.asList(ignoreProperties):null;
PropertyDescriptor[]var7=targetPds;
intvar8=targetPds.length;

for(intvar9=0;var9<var8;++var9){
PropertyDescriptortargetPd=var7[var9];
//getWriteMethod中註釋說明
//Mayreturnnullifthepropertycan'tbewritten.
//也就是說對應的類中必須有set(寫入)方法,否則返回空
MethodwriteMethod=targetPd.getWriteMethod();

System.out.println("=======================");
if(writeMethod!=null&&(ignoreList==null||!ignoreList.contains(targetPd.getName()))){
//取出對應的屬性並讀取值
System.out.println(targetPd.getName());
//source.getClass().getDeclaredFields();
PropertyDescriptorsourcePd=getPropertyDescriptor(source.getClass(),targetPd.getName());
//System.out.println(sourcePd.getClass().getDeclaredFields().toString());
//booleanf=false;
//if(!Objects.isNull(sourcePd)){
//Field[]declaredFields=sourcePd.getClass().getDeclaredFields();
//System.out.println("ppppppppppppppppp"+declaredFields.length);
//if(declaredFields.length>0){
//for(FielddeclaredField:declaredFields){
//judgefieldAnnotation=declaredField.getDeclaredAnnotation(judge.class);
//if(fieldAnnotation!=null){
//f=true;
//System.out.println("1111111111111");
//}
//}
//}
//}
if(sourcePd!=null){
MethodreadMethod=sourcePd.getReadMethod();
if(readMethod!=null&&ClassUtils.isAssignable(writeMethod.getParameterTypes()[0],readMethod.getReturnType())){
try{
if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())){
readMethod.setAccessible(true);
}

Objectvalue=readMethod.invoke(source);
//Field[]declaredFields=source.getClass().getDeclaredFields();

System.out.println(value);
if(!Objects.isNull(value)){
if(!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())){
writeMethod.setAccessible(true);
}
Field[]declaredFields=target.getClass().getDeclaredFields();
inti=0;
for(FielddeclaredField:declaredFields){
judgefieldAnnotation=declaredField.getDeclaredAnnotation(judge.class);
if(fieldAnnotation!=null){
if(targetPd.getName().equals(declaredField.getName())){
i++;
}
//System.out.println(declaredField.getName());
}

}
if(i==0){
//寫入對應的值到目標類關鍵
writeMethod.invoke(target,value);
}
}
//if(!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())){
//writeMethod.setAccessible(true);
//}
//Field[]declaredFields=target.getClass().getDeclaredFields();
//inti=0;
//for(FielddeclaredField:declaredFields){
//judgefieldAnnotation=declaredField.getDeclaredAnnotation(judge.class);
//if(fieldAnnotation!=null){
//if(targetPd.getName().equals(declaredField.getName())){
//i++;
//}
////System.out.println(declaredField.getName());
//}
//
//}
//if(i==0){
////寫入對應的值到目標類關鍵
//writeMethod.invoke(target,value);
//}
//寫入對應的值到目標類關鍵
//writeMethod.invoke(target,value);
}catch(Throwablevar15){
thrownewFatalBeanException("Couldnotcopyproperty'"+targetPd.getName()+"'fromsourcetotarget",var15);
}
}
}
}
}

}

}

核心是

Field[]declaredFields=target.getClass().getDeclaredFields();
inti=0;
for(FielddeclaredField:declaredFields){
judgefieldAnnotation=declaredField.getDeclaredAnnotation(judge.class);
if(fieldAnnotation!=null){
if(targetPd.getName().equals(declaredField.getName())){
i++;
}
//System.out.println(declaredField.getName());
}

}
if(i==0){
//寫入對應的值到目標類關鍵
writeMethod.invoke(target,value);
}

執行看效果

看到裡面的值還是沒有改變 解決

需求2:如果A中某欄位沒值(為null),則該欄位不復制 也就是不要把null複製到B當中

上面還是可以用

核心

Objectvalue=readMethod.invoke(source);
//Field[]declaredFields=source.getClass().getDeclaredFields();

System.out.println(value);

看結果

看到

publicclassYY{
publicstaticvoidmain(String[]args)throwsInvocationTargetException,IllegalAccessException{
DepartmentidDtodepartment=newDepartmentidDto();
department.setDepartmentid(1);

department.setDepartmentname("2222222222222");
Departmentdepartmentid=newDepartment();
//
departmentid.setDepartmentname("3333333333333333333");
departmentid.setHh("12314");

//前面是dtoa後面是pojob
BeanUtilsVo.copyProperties(department,departmentid);
System.out.println(departmentid.toString());


}
}

日誌

=======================
=======================
departmentid
1
=======================
departmentname
2222222222222
=======================
hh
null
=======================
managerid
Department(departmentid=1,departmentname=3333333333333333333,managerid=null,hh=12314)

希望可以給大家帶來看原始碼的能力,和學習這個方法的原始碼是幹什麼的,怎麼進行根據需求去改造這個原始碼,謝謝你的支援,這個問題,百度上也有,但是寫的,看不懂,這個寫的比較簡單,希望給你帶來學習的意義,去理解複製的原理

對這個需求有問題可以加我微信