background
Some time ago in the work, including some code reading process, spring AOP will often see the related content in the Cglib, including Beancopier,bulkbean,enancher and so on content, although previously knew some content, the principle is through bytecode, But not specific in-depth code research, only know its use do not know why, so it took a long time to study the cglib of the relevant source, while combining the next spring AOP in the use of cglib.
This article mainly through the Cglib has the principle analysis, the reverse compiles the view source, the example and so on the way makes an introduction. cglib Basic Information cglib official website: http://cglib.sourceforge.net/cglib Current version should be 2.2, the company's widely used version is also the official website of the samples:http:// cglib.sourceforge.net/xref/samples/ cglib Code Packet Structure core (core code) emitutils reflectutils keyfactory classemitter/ Codeemitter Namingpolicy/defaultnamingpolicy generatorstrategy/defaultgeneratorstrategy DebuggingClassWriter Classgenerator/abstractclassgenerator Beans (Bean operation Class) Beancopier Bulkbean beanmap Immutablebean BeanGenerator reflect Fastclass Proxy enhancer callbackgenerator Callback methodinterceptor, Dispatcher, Lazyloader, Proxyrefdispatcher, No Op, Fixedvalue, Invocationhandler (providing functionality with JDK proxy) Callbackfilter util stringswitcher Parallelsorter transform Co Re core code section emitutils
Important tool class, mainly encapsulates some basic functions of operation bytecode, such as generating a null_constructor, adding class attribute Add_property and so on reflectutils
A tool class that handles JDK reflect, such as obtaining all methods of a class, obtaining constructor information, and so on. Classemitter/codeemitter
The implementation of Classadapter and Methodadapter of ASM runs through the process of Cglib code keyfactory
The important unique identifier generator in the class library, which is used to do the map key when cache is cglib, and to compare the underlying class.
Example:
Interface
Bulkbeankey {
Public
Object
newinstance (string
target, String
[] getters, string [
] Setters, string
[] Types);
}
(Bulkbeankey) Keyfactory.create (Bulkbeankey.class). newinstance (Targetclassname, getters, setters, typeclassnames);
Note: Each key interface must provide a newinstance method, but the specific parameters can be arbitrarily defined, returned by the newinstance as a unique indicator, only if all incoming parameters of the equals return True, the generated key is the same, This is equivalent to the concept of multiple key. Namingpolicy
Default implementation class: Defaultnamingpolicy, specific cglib dynamically generated class naming control.
General naming rules: the proxy class name + "$$" + cglib Processing of class name + "Bycglib" + "$$" + key Hashcode Example: Fastsource $ $FastClass bycglib$$ E1a36bab.class generatorstrategy
Default implementation class: Defaultgeneratorstrategy
Control Classgenerator generates byte data for class and inserts its own processing in the middle. Note that this relies on: Debuggingclasswriter for Class generator processing debuggingclasswriter
The cglib encapsulates the ASM processing class, which is used to generate the byte stream of class, through Generatorstrategy callback Classgenerator.generateclass (Debuggingclasswriter), The custom class byte processing callback is given to the specific Cglib upper class, for example, by a specific beancopier to control the generation of bytecode. Classgenerator
One of the abstract implementations: Abstractclassgenerator. Cglib code in the core class bytecode operator, including some cache, call namingpolicy,generatorstrategy for processing, can be said to be one of the most central dispatchers.
the corresponding class diagram:
the outer beancopier contain a generator that inherits from the Abstractclassgenerator, implements Generateclass (Classvisitor v), Object firstinstance (Class type) method. Abstractclassgenerator itself will be based on the source cache, so for the class has been generated, here keyfactory corresponding values to be equal, it will return directly to the cache results. So beancopier each time you create a slow only need new two objects, one is Keyfactory.newinstance, the other is Firstinstance method calls to generate an object. Reverse Compile Tips
We all know cglib is to carry out bytecode operation, will dynamically generate class, the fastest and most direct learning is the combination of his generation of class, control code to learn, the effect will be much better. Java Code system.setproperty (debuggingclasswriter.debug_location_property, "Specify Output directory");
You can see the Cores/debuggingclasswriter code. Description: This cglib will output each class dynamically generated to the file, and then we can decomp to see the source code.
Beans (Related operation Class) Beancopier
Simple sample Code does not introduce, I believe we all guide how to use, here is the main introduction of the use of convert. Many netizens have done beancopier,beanutils test, the basic beancopier performance is beanutils more than 10 times times. , the performance difference of reflection, beanutils by default is to turn on the converter function, allowing the same name, different types of properties to copy, such as Date object to string property. Interested students can go to compare the next propertyutils, the default does not open converter function, found that performance is beanutils twice times more.
Initialization example: Beancopier copier = beancopier.create (Source.class, Target.class, true);
The third parameter useconverter, whether to turn on convert, the default beancopier will only do the same name, the same type of property copier, otherwise it will be an error. Converter Use example code public class beancopiertest { public static void main (string args[]) { system.setproperty (debuggingclasswriter.debug_location_property, "/TMP/1"); BeanCopier copier = Beancopier.create (source.class, target.class, true); source from = new source (); from.setvalue (1); target to = new target (); converter converter = new bigintconverter (); &nbsP copier.copy (from, to, converter); // Use the converter class system.out.println ( To.getvalue ()); } } class bigintconverter implements net.sf.cglib.core.converter { @Override public object convert (Object value, class target, object context) { system.out.println (Value.getclass () + " " + value); // Value Object system.out.println (target) in the From class; // The parameter objects defined in the to class system.out.println ( Context.getclass () + " " + context); // string object, specific method name if ( Target.isassignablefrom (Biginteger.class)) { return new biginteger (Value.tostring ()); } else { return value; } } } ---- back-compiled code: public class target$ $BeanCopierByCGLIB $ $e 1c34377 extends beancopier { public void copy (Object obj, object obj1, converter converter) { target target = (Target) obj1; source source = (Source) obj; // Note is called directly, Did not pass reflect target.setvalue (BigInteger) Converter.convert (New integer (Source.getvalue ()), cglib$load_class$java$2emath$2ebiginteger, " SetValue "); } }
Use caution to avoid creating objects each time you beancopier.create, it is generally recommended that you use converter with the static beancopier copier = Beancopier.create (). Scenario: Two copies of data with the same name as the same attribute between objects, and cannot be individually copied for several of these properties Bulkbean
Allows you to customize the properties of a process compared to the Beancopier,bulkbean two ways to split the entire copy action into getpropertyvalues,setpropertyvalues.
Java code public class BulkBeanTest { public static void main (string args[]) { system.setproperty (debuggingclasswriter.debug_location_property, "/home/ljh /cglib "); string[] getter = new String[] { "GetValue" }; String[] setter = new String[] { "SetValue" }; class[] clazzs = new Class[] { Int. Class };