Technical precipitation of object copy class Propertyutils,beanutils,beancopier
Performance comparison: beancopier > Propertyutils > Beanutils. The performance of Beancopier is higher than the other two 100 orders of magnitude.
Beancopier use can be consulted: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp36
Introduction to the application of object copying:
It is often necessary to copy the properties of two objects in a business system, and it is not possible to deny that the object copy is the fastest and safest way, but the code becomes bloated when the number of attribute fields of the data object exceeds the programmer's tolerance, and it is a good choice to use some handy object copy tool classes.
The more commonly accepted tool classes are now popular:
Two versions of Apache: (Reflection mechanism)
Org.apache.commons.beanutils.PropertyUtils.copyProperties (Object dest, Object orig)
Org.apache.commons.beanutils.BeanUtils.copyProperties (Object dest, Object orig)
Spring version: (Reflection mechanism)
Org.springframework.beans.BeanUtils.copyProperties (object source, object target, Class editable, string[] Ignoreproperties)
Cglib version: (Use dynamic agent, high efficiency)
Net.sf.cglib.beans.BeanCopier.copy (Object ParamObject1, Object ParamObject2, Converter paramconverter)
Principle Introduction Reflection Type: (Apache)
Both use static class calls and eventually convert two singleton tool objects in a virtual machine.
Public Beanutilsbean ()
{
This (new Convertutilsbean (), new Propertyutilsbean ());
}
Convertutilsbean can be registered by Convertutils global customization.
Convertutils.register (New Dateconvert (), java.util.Date.class);
The Copyproperties method of Propertyutilsbean implements the algorithm of copying.
1, dynamic Bean:orig instanceof Dynabean:object value = ((Dynabean) orig). Get (name), and then copy value to the Dynamic bean class
2. Map type: Orig instanceof Map:key Value-by-copy
3, Other Ordinary class:: From BeanInfo "Each object has a cached bean information, including attribute fields, etc." Take out name, then copy the Sourceclass and Targetclass one by one
Cglib Type: Beancopier
Copier = Beancopier.create (Source.getclass (), Target.getclass (), false);
Copier.copy (source, target, NULL);
Create object procedure: Generate sourceclass-"Targetclass copy proxy class, put into the JVM, so the creation of proxy classes is time-consuming. It is best to ensure that the singleton pattern of this object can be referred to the last part of the optimization scheme.
Creation process: source code See Jdk:net.sf.cglib.beans.BeanCopier.Generator.generateClass (Classvisitor)
1. Get all public get methods of Sourceclass-"propertydescriptor[] getters
2. Get all public set methods of Targetclass-"propertydescriptor[] Setters
3. Traverse each property of setters, execute 4 and 5
4, according to Setters name Generation Sourceclass All Setter Method-"PropertyDescriptor getter" class that does not conform to the JavaBean specification will likely have a null pointer exception "
5, propertydescriptor[] setters-"PropertyDescriptor setter
6, the setter and getter name and type pair, generate proxy class copy method.
Copy Property procedure: Call the generated proxy class, the code of the proxy class and the Code of the manual operation are very similar, very efficient.
Defect prevention
You don't know the traps, do you?
Trap conditions |
Apache-propertyutils |
Apache-beanutils |
Spring-beanutils |
cglib- Beancopier |
Whether you can extend Useconvete function |
NO |
Yes |
Yes |
Yes, but it's more difficult to use |
(Sourceobject,targetobject) in order |
Reverse |
Reverse |
Ok |
Ok |
Restrictions on SourceObject special attributes: (Date,bigdecimal, etc.) "See note 1" |
Ok |
NO, abnormal error |
Ok |
Ok |
Processing with the same property name and when the type does not match "See note 2" |
Abnormal, copy some attributes, very dangerous |
OK, and can perform a primary conversion, long and integer to each other |
exceptions, copying partial attributes |
OK, but this property does not copy |
Handle mismatch of get and set methods "See note 3" |
Ok |
Ok |
Ok |
Error when creating copy, unable to copy any attributes (when and only if Sourceclass's get method exceeds set method) |
Remark 1
Restrictions on TargetObject special attributes: (Date,bigdecimal, etc.) Cause: The conveter of datetimeconveter does not handle null values |
Public class Errorbeanutilobject { //Omit Getter,setter method here Private String name; private java.util.Date Date; } Public class errorbeanutilstest { Public static void main (String args[]) throws Throwable { Errorbeanutilobject from = new errorbeanutilobject (); Errorbeanutilobject to = new errorbeanutilobject (); From.setdate (new java.util.Date ()); From.setname ("tttt"); Org.apache.commons.beanutils.BeanUtils. copyproperties (To, from);//If From.setdate is removed, Conveter exception appears here System. out. println (Tostringbuilder. Reflectiontostring(from)); System. out. println (Tostringbuilder. Reflectiontostring(to)); } } |
Remark 2
Processing with the same property name and when the type does not match Cause: The two tool classes do not support matching of different types with the same name!!! "Wrapper class long and original data type Long is OK" |
Public class Targetclass { //Omit Getter,setter method here Private Long num; Private String name; } Public class Targetclass { //Omit Getter,setter method here Private Long num; Private String name; } Public class errorpropertyutilstest { Public static void main (String args[]) throws illegalaccessexception, InvocationTargetException, nosuchmethodexception { Sourceclass from = new sourceclass (); From.setnum (1); From.setname ("name"); Targetclass to = new targetclass (); Org.apache.commons.beanutils.PropertyUtils. copyproperties (To, from); Throw parameter mismatch exception Org.springframework.beans.BeanUtils. copyproperties (from, to); Throw parameter mismatch exception System. out. println (Tostringbuilder. Reflectiontostring(from)); System. out. println (Tostringbuilder. Reflectiontostring(to)); } } |
Remark 3
Handle mismatch of get and set methods |
Public class errorbeancopiertest { /** * See from this use case that every get method of beancopier.create Target.class must have a set method of formation * @param args */ Public static void main (String args[]) { Beancopier copier = beancopier. Create (Unsatifisedbeancopierobject. class, Sourceclass. class,false); Copier = Beancopier. Create (Sourceclass. class, Unsatifisedbeancopierobject. class, false); Throws exception created here } } class Unsatifisedbeancopierobject { Private String name; Private Long num; Public String GetName () { return name; } Public void setName (String name) { this. Name = name; } Public Long Getnum () { return num; } public void Setnum (Long num) { This.num = num; // } } |
Optimization scenarios
Some optimizations and improvements
Enhanced copy properties of Apache Beanutils, registering some new type conversions |
public class Beanutilsex extends beanutils { public static void Copyproperties (Object dest, Object orig) { try { beanutils.copyproperties (dest, orig); } catch (Illegalaccessexception ex) { ex.printstacktrace ( ); } catch (InvocationTargetException ex) { Ex.printstacktrace (); } } Static { convertutils.register (New Dateconvert (), java.util.Date.class); Convertutils.register (New Dateconvert (), java.sql.Date.class); Convertutils.register (New Bigdecimalconvert (), bigdecimal.class); } } |
Make Beancopier static class for easy copy |
Public class beancopierutils { Public Static map<string,beancopier> Beancopiermap = new hashmap<string,beancopier> (); Public static void Copyproperties (object source, object target) { String Beankey = generatekey(Source.getclass (), Target.getclass ()); Beancopier copier = null; if (! beancopiermap. ContainsKey (Beankey)) { Copier = Beancopier. Create (Source.getclass (), Target.getclass (), false); Beancopiermap. Put (Beankey, copier); }Else{ Copier = Beancopiermap. Get (Beankey); } Copier.copy (source, target, null); } private static String GenerateKey (class<?> class1,class<?>class2) { return class1.tostring () + class2.tostring (); } } |
Fix the constraint of beancopier on the strong limit of Set method |
Overwrite Net.sf.cglib.beans.BeanCopier.Generator.generateClass (Classvisitor) method The 133-row MethodInfo write = Reflectutils.getmethodinfo (Setter.getwritemethod ()); Pre-save a names2 into /* 109 */Map Names2 = new HashMap (); /* * for (int i = 0; i < getters.length; ++i) { /* 111 */Names2.put (Setters[i].getname (), getters[i]); /* */ } Call this line of code before the query, if not changed Writemethod ignore the operation of the field, so you can avoid the occurrence of the exception. |
Transfer from HTTP://BLOG.YEMOU.NET/ARTICLE/QUERY/INFO/TYTFJHFASCVHZXCYTP37
Technical precipitation of object copy class Propertyutils,beanutils,beancopier