JBULL is a very simple library for standard/mostly used java bean operations. Such operations are copy, clone, equality. It is interesting that such operations are not provided by standard J2SE.
There are already some open source projects that cover this simple topic. Unfortunately performance they offer is really disappointing.
Whole the project is still in early beta phase. It means it works for me but I wish it worked for anybody else. I am awaiting comments and issues. I strongly insist on not using it (yet) in mission critical projects!
For additional information see sourceforge project page.
This lib provides two basic operations:
BeanHelper.copy(Object src, Object dst)
BeanHelper.equals(Object src, Object dst)
This is the easiest way to perform copy operation. Lets check example:
MyClassOne sourceBean = .... // this is source bean
MyOtherClass destBean = new MyOtherClass(); // this is target bean
...
BeanHelper.copy(sourceBean, destBean); //this is copy operation
Copy for java beans means: copy all valid java beans properties. There are no restrictions on any dependencies between target and source classes (neither inheritance nor common interface is needed).
Performance note: Introspection is known to be time consuming - and it really is. In order to provide fastest possible speed this method uses some caching. However, it does not simply cache introspection result, but in fact it stores the ready list of primitive method.invoke operations that are needed to perform desired high-level operation !!!
The mentioned, cached set of operation can be stored as BeanWorker (operation object). This there are checks against cache avoided. Which proved to give some measurable speed improvement.
Example:
/**
* this field stores worker
*/
private final BeanWorker< MyClassOne, MyOtherClass> worker =
BeanHelper.getWorker(MyClassOne.class,MyOtherClass.class );
....
{
MyClassOne sourceBean = .... // this is source bean
MyOtherClass destBean = new MyOtherClass(); // this is target bean
...
this.worker.copy( sourceBean, destBean);
...
}
This feature is experimental -> it works but the way it works may change. Especially that current aproach is very dangerous and may be unpredictable under some circumstances!!!
Although, getWorker brings really huge speed - it is sure that set of
reflective calls (Method.invoke
) will be usually slower
(not faster) than simple compiled code with set of
dst.setXYZ (src.getXYZ() );
operations.
hanks to the newest cool features of JAVA 5.0 it was possible to introduce simple code generator for beans operations. In order to use it developer has to do some additional tasks:
public class MyClass { ...
/**
* this field stores STATIC worker
*/
@StaticCopier
private final BeanWorker< MyClassOne, MyOtherClass> worker =
BeanHelper.findStaticWorker(MyClass.class);
....
{
MyClassOne sourceBean = .... // this is source bean
MyOtherClass destBean = new MyOtherClass(); // this is target bean
...
this.worker.copy( sourceBean, destBean);
...
}
Not so many things have changed in this code. It is important to know that this method will be working also if apt task was not performed during the build - or if it has failed. In such case - normal runtime worker will be created (@todo!!). This means that it is easy to turn it on or off and check the impact on performance during for instance project testing phase!!! Only the build process has to be changed.
You those operations to create per thread helper. And to dispose memory consumed by workers cache.
You this for thread safe operations.
List of things I plan to do in order to call this product version 1.0:
Future plans:
Please, go to sourceforge project page.
method | time (ms) |
---|---|
BeanHelper.copy simple |
17594 |
BeanWorker.copy() stored worker |
6563 |
.copy() Custom copy method (written) |
78 |
staticCopy Generated copy method (APT) |
78 |
other libraries | |
dozer | 458594 |
beanlib | 519547 |
beanutils | 1584875 |
beanutils2 | 563375 |
Test machine: Pentium 4 3GHZ,HT, 1GB RAM
JVM: Java HotSpot(TM) Server VM (build 1.5.0_04-b05, mixed mode)
JVM args: -server -Xmx128m -Xms128m -XX:CompileThreshold=100
See CopyBenchmarkTest.class
for details.
There were 9999999 basic operations performed, before each measured loop there was small loop with 9999 operations called.
As I wanted to test my framework from the begining there is set of benchmarks ready -> see tests package. I compared my solution to other: beanlib, commons-beanutils. Although benchmark may suggest my solution is a "hell" faster I do not say that ( :-) ):