Use javassist enhancement ValueObject object function - to ValueObject property Get and Set methods

ValueObject long days, the company developed its own data manipulation objects, it provides a configuration file automatically generated POJO object function, automatically generate simple SQL statements, dynamic SQL to read the configuration file statement in the implementation of database operations and other functions, for systems development with a great convenience, greatly improve the efficiency of development, reducing development time, shortening the project cycle, is widely used in various projects.
However, ValueObject object to the developer provides a convenient, there are some flaws, sometimes with some trouble to develop and increase the amount of code. For example: ValueObject Use Map to store the attribute "key - value" data, in the operation of property, not subject to normal POJO objects to use as way of operation setXXX getXXX or property, but must be used with attribute names such as getString (XXX) and setString (XXX, value) way to operate. For this reason, the use of labels in Struts1.X ValueObject object, can not use the "VO object name. Attribute name" method to use, but must be changed to "VO object name. String (attribute name)," This will not only increase by only the amount of code, and in some cases would lead to other problems; in Struts2, because Struts2 operation mode object properties change, leading to not use the "VO object name. string (property name)" methods to manipulate properties, and must be changed to "VO object name. values [attribute name]" approach, so that the object in the direct operation of the properties of Map, destroyed the encapsulation, but also to the development caused no small trouble.
In the most recent period, we rent in Xiamen, performance evaluation using Struts2 development projects, the sensory ValueObject of such restrictions to the development zone has a lot of trouble, so I have been looking for a way to transform ValueObject object, so that Nenggen normal The POJO object as operating property, so that nowadays widely used to improve and some software compatibility framework.
Speaking to transform ValueObject object, I must face a reality: ValueObject has been widely used in various projects, how to transform to ensure compatibility so that existing projects do not make any changes? Better solution is made to modify the content of plug-in, when needed, you can use to increase the function call, do not call that by the original use. If you can do plug-in, you can do non-invasive, it can ensure compatibility with existing systems, the. However, how to design the plug-in then?
Reference to a variety of popular application development framework, the most popular and most effective than AOP, while no more than two kinds of means to achieve AOP: reflection and dynamic code generation. Reflection is provided by the JDK itself, its characteristic is easy to use, OO Texing good, but the disadvantage is low efficiency, to achieve Gongnengyouxian; Dongtai Daimashengcheng feature is the byte code of Cengci right Lei Jinxingxiugai, Yi Dan modification completed, Jiu no longer have performance loss, so much higher than the reflection of operating performance, shortcomings is that most of the code generation tool to understand the dynamic JVM specification defines the structure of the byte code basis.
By comparison, I found that reflection can not meet my requirements, can only resort to bytecode modification tool. Bytecode in the popular tools, ASM is the best performance, smallest, but ease of use is not good, I search the web for a long time, are not found to much information for reference, so chose javassist, Although it can not match the performance and size of ASM, but the ease of use, very good, according to the way OO can modify the class.
Established rehabilitation programs, the transformation began.

The first step: Get javassist.jar:
Download the latest from the www.javassist.org javassist.jar package, the way a bit concerned about its environmental requirements, it requires JDK 1.3 or above, this requirement for our project in general can achieve.

Step Two: Analysis of how to increase ValueObject property Get, Set method, and how dynamically generated code:
POJO object because ValueObject is common to each class has different properties in different Model, we can not directly modify the class to generate the property ValueObject method of operation, so we need for each Model with attributes How to generate a class, the class from ValueObject class inheritance, each need to generate ValueObject Model instance, created under Model names correspond to class. Model corresponding to the dynamically generated class code is as follows:
1. / **
2. * Generate a subclass of the original class
3. * @ Param clz Class ValueObject class
4. * @ Param newName String need to generate a new class of class name
5. * @ Return CtClass javassist class packing objects
6. * @ Throws NotFoundException
7. * @ Throws CannotCompileException
8. * @ Throws RuntimeException
9. * /
10.protected CtClass makeNewClass (Class clz, String newName)
1. Throws NotFoundException, CannotCompileException, RuntimeException (
2. Class _clz = clz;
3. String _clzName = _clz.getName (); / / get the class name ValueObject
4.
5. CtClass _cClass = null;
6.
7. / / Get javassist the ClassPool (javassist generated or changed the new class are placed ClassPool in
8. / / For use in the next revised)
9. ClassPool _pool = ClassPool.getDefault ();
10.
11. Try (
12. / / See if need to generate the class already exists,
13. / / Method is to try to ClassPool in the generated class name needed to take CtClass,
14. / / If we can get that shows class already exists, will not repeat generation
15. _cClass = _pool.get (NewName); / / fetch from ClassPool
16. Throw new RuntimeException ("Class already exists.");
17.) Catch (NotFoundException ex) (
18. Log.debug (ex);
19. / / According to the new class name to generate a new class
20. _cClass = _pool.makeClass (NewName);
21.
22. / / The parent class of the new class set ValueObject class
23. _cClass.setSuperclass (_pool.get (_clzName));
24.
25. / / To generate a new class default constructor to use Class.newInstance () method generates a class instance,
26. / / But this requires the parent class has a constructor without parameters.
27. / / New class default constructor is not necessary, as long as the parent class constructor can be with or without parameters.
28. / / CtConstructor cons = CtNewConstructor.defaultConstructor (_cClass);
1. / / _cClass.addConstructor (Cons);
1.)
2. Return _cClass;
3.)

According to Model of the property, call the javassist to build a new generation of Class Get and Set methods:

1. / **
2. * According to VO in the property value method of generating getXXX and setXXX
3. * @ Param newVoClass CtClass steps in front of the new generated class (inherited from ValueObject)
4. * @ Param vo ValueObject with the new instance of the Correspondence Model of ValueObject
5. * @ Throws CannotCompileException
6. * /
7.protected void makeGetSet (CtClass newVoClass, ValueObject vo)
1. Throws CannotCompileException (
2. / / Remove all the properties in the name of Model
3. String [] fieldNames = getFiledNames (vo);
4.
5. / / Loop for each property Set and Get methods to increase
6. For (int ii = 0; ii <fieldNames.length; ii + +) (
7. Object _obj = vo.getObject (fieldNames [ii]);
8. / / Get the type of corresponding attribute
9. Class type = _obj.getClass ();
10. / / The property name was changed to lowercase and capitalized string
11. String filedName = StringUtils.capitalise (fieldNames [ii]. ToLowerCase ());
12.
13. / / Set setXXX method
14. / / Set method to construct the source code
15. StringBuffer func = new StringBuffer ("public void set"). Append (filedName). Append ("("). append (type.getName ()). Append ("value) (");
16. Func.append ("this.setObject (\" "). Append (fieldNames [ii]). Append (" \ ", value);");
17. Func.append ("}");
18. / / Set method of generating
19. CtMethod setM = CtNewMethod.make (func.toString (), newVoClass);
20. NewVoClass.addMethod (setM);
21.
22. / / Set getXXX method
23. / / Get method to construct the source code
24. Func = new StringBuffer ("public"). Append (type.getName ()). Append ("get"). Append (filedName). Append ("() (");
25. Func.append ("return ("). Append (type.getName ()). Append (") this.getObject (\" "). Append (fieldNames [ii]). Append (" \ ");" );
26. Func.append ("}");
27. / / Set method of generating
28. CtMethod getM = CtNewMethod.make (func.toString (), newVoClass);
29. NewVoClass.addMethod (getM);
30.)
31.)
32.
33. / **
1. * Remove all attributes from ValueObect name
2. * @ Param vo MyValueObject
3. * @ Return String []
4. * /
5.protected String [] getFiledNames (ValueObject vo) (
1. String [] names = new String [vo.getValues (). Size ()];
2. Set keys = vo.getValues (). KeySet ();
3. Iterator it = keys.iterator ();
4. Int ii = 0;
5. While (it.hasNext ()) (
6. Names [ii + +] = ((String) it.next ());
7.)
8. Return names;
9.)
Call the above method to generate new classes and properties generated under the Get and Set methods, then converted to byte array:

1. / **
2. * Generate a new class of bytes of code
3. * @ Param clz Class ValueObject class
4. * @ Param newName String name to generate a new class
5. * @ Param vo ValueObject original ValueObject objects removed from the property name and property type
6. * @ Return byte [] byte data generated class
7. * @ Throws RuntimeException
8. * @ Throws CannotCompileException
9. * @ Throws NotFoundException
10. * @ Throws IOException
11. * /
12.public byte [] generate (Class clz, String newName, ValueObject vo)
1. Throws RuntimeException, CannotCompileException, NotFoundException, IOException (
2. Byte [] data = null;
3. / / Generate a new class
4. CtClass _cc = makeNewClass (clz, newName);
5. / / Get and Set methods of generating
6. MakeGetSet (_cc, vo);
7. / / The class file is written to disk
8. / / _cc.writeFile ();
9. / / The class into a byte array
10. Data = _cc.toBytecode ();
11. / / The class from the ClassPool CtClass just deleted to save memory
12. _cc.detach ();
13. Return data;
14.)

Generated with Get and Set methods ValueObject class, then generate an instance, and to all of the original ValueObject object value is assigned to the new class:

1. / **
2. * Increase of the class
3. * @ Param vo ValueObject original ValueObject class POJO objects
4. * @ Return ValueObject generated ValueObject new subclass of POJO objects
5. * @ Throws RuntimeException
6. * @ Throws CannotCompileException
7. * @ Throws NotFoundException
8. * @ Throws IllegalAccessException
9. * @ Throws InstantiationException
10. * @ Throws IOException
11. * /
12.public MyValueObject enhance (ValueObject vo) (
1. ValueObject _vo = vo;
2.
3. / / Model name under the VO object to generate a new class name
4. StringBuffer _newClzName = new StringBuffer (vo.getClass (). GetName ());
5. _newClzName.append (Vo.getModelName () == null? "": ("$" + Vo.getModelName ()));
6.
7. / / Private static final String CLS_SUFFIX = "$ EnhancedBySYF";
8. _newClzName.append (CLS_SUFFIX);
9.
10. Class _voClz = null;
11.
12. Try (
13. Try (
14. / / First call the class loader tries to load the new class, if the class has been generated, you can load successfully,
15. / / Do not need a new generation renewable
16. / / Private static EnhancedValueObjectGeneratorClassLoader loader = new EnhancedValueObjectGeneratorClassLoader ();
17. _voClz = Loader.loadClass (_newClzName.toString ());
18.) Catch (ClassNotFoundException ex) (
19. Log.debug (ex);
20. / / If the class loader to find a new class, if not, then generate a new class
21. Byte [] data = generate (vo.getClass (), _newClzName.toString (), vo);
22. / / Generate class byte array generated according to class
23. _voClz = Loader.defineClass (_newClzName.toString (), data);
24.)
25. If (_voClz! = Null) (
26. / / To generate a new class instance, then the original property of the object assigned to the new VO VO object
27. / / Here use the newInstance method to instantiate the class, there is a need ValueObject class
28. / / Public or Protected no-argument constructor, so they need a small modification ValueObject class
29. _vo = (ValueObject) _voClz.newInstance ();
30. Vo.ConvertAnotherVO (_vo);
31.)
32.) Catch (RuntimeException ex) (
33. Log.warn ("Enhance [ValueObject] object failed, return original object.");
34.) Catch (CannotCompileException ex) (
35. Log.warn ("Enhance [ValueObject] object failed, return original object.");
36.) Catch (NotFoundException ex) (
37. Log.warn ("Enhance [ValueObject] object failed, return original object.");
38.) Catch (IllegalAccessException ex) (
39. Log.warn ("Enhance [ValueObject] object failed, return original object.");
40.) Catch (InstantiationException ex) (
41. Log.warn ("Enhance [ValueObject] object failed, return original object.");
42.) Catch (IOException ex) (
43. Log.warn ("Enhance [ValueObject] object failed, return original object.");
44.)
45. Return _vo;
46.)
47.
48. In order to call defindClass method requires a custom class loader:
49. / **
1. * Custom class loader
2. * @ Author not attributable
3. * @ Version 1.0
4. * /
5.private static class EnhancedValueObjectGeneratorClassLoader extends ClassLoader (
1. Public Class defineClass (String className, byte [] classFile) throws ClassFormatError (
2. Return defineClass (className, classFile, 0, classFile.length);
3.)
4.)
The third step: how to use the tools it:
The following section of code to demonstrate how by using the tools:

1.ArrayList cpList = JxcpMgr.getCpList (String userid);
2.ArrayList newCpList = new ArrayList ();
3.EnhancedValueObjectGenerator enhancer = new EnhancedValueObjectGenerator ();
4.for (int ii = 0; ii <cpList.size (); ii + +) (
1. ValueObject vo = (ValueObject) cpList.get (ii);
2. / / To the increase in VO Get, Set obtained the new class, and placed in the new List
3. NewCpList.add (enhancer.enhance (vo));
4.)
/ * In the JSP in the * /

1. <logic:iterate Property="newCpList" name="rycpForm">
2. <tr>
3. <td> User code: <html:text name="cpjl" property="USER_ID" size="10" /> </ td>
4. <td> Unit code: <html:text name="cpjl" property="DW_ID" size="10" /> </ td>
5. <td> Assessment Score: <html:text name="cpjl" property="CPDF" size="15" /> </ td>
6. <td> Evaluation rating: <html:text name="cpjl" property="CPDJ" size="10" /> </ td>
7. </ Tr>
8. </ Logic: iterate>
Conclusion:
Byte code tool gives us a very good tool, so that we can freely insert the code in any class, truly aspect-oriented programming. Good use of such tools, can give us tremendous flexibility in developing the framework, the framework of development time when we feel him, he may wish to open ideas, try dynamically generated code.
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of Use javassist enhancement ValueObject object function - to ValueObject property Get and Set methods

  • java read file

    java read documents in two ways: java.io and java.lang.ClassLoader When using the java.io, when java.lang.ClassLoader use it? (Note: If prior to read xml file java read file clearly aware of these two methods have been like! Can take much less to understa

  • Hibernate primary key strategy-sequence

    Today, the use of hibernate in the company encountered a troublesome problem, the use of hibernate when the primary key generation strategy set sequence, but always reported in the implementation could not get next sequence value of the error, then o ...

  • Hibernate pessimistic locking mechanism for locking and optimistic locking

    hibernate lock mechanism 1. Pessimistic lock It refers to the modification of data by outsiders hold a conservative attitude. The assumption that at any time access to data, may also have another client to access the same data, in order to maintain t ...

  • Hibernate configuration parameters hibernate.hbm2ddl.auto

    Hibernate in the configuration file: <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </ properties> Parameter Description: validate load hibernate, the authentication to create a database t ...

  • Nan-Jing 5: When IBatis.Hibernate mixed affairs, pay attention to your SQL

    [Problem] Now, in the development of the so-called multi-storey JavaEE applications, data persistence layer is always essential, and "Automatic" of ORM - Hibernate, and "all-manual-type" of SqlMap - IBatis, equivalent data are Per ...

  • hibernate to use the principle of

    The use of hibernate, implementation of data persistence. Has the following several processes. One configuration database connection information. Hibernate.config 2 configuration mapping. 3 use: the use of the process are the following steps: 3.1: Ge ...

  • Struts2 + hibernate + spring problem user log in

    dao layer services layer action jsp <tr> <td align="center"> <b> user name: </ b> </ td> <td> <s: textfield name = "czyNumber" cssClass = "textstyle" theme = "simple" size = &q

  • Based on JDBC, JPA Annotation achieve simple CRUD Generic Dao

    The origin of ideas are pretty long history of reasons: [Use iBATIS history] The use of iBATIS has been a long time, the system is to use the CRUD template tool to generate the code, although there are tools to generate, but looked at a lot of CRUD the Sq

  • Hibernate's lazy strategy

    hibernate Lazy strategy can be used in: <class> tag, it can be true / false Tags can <PROPERTY> values true / false type of necessary tools to enhance <set> <list> can tag values true / false / extra <many-to-one> <on ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries