Iii. ASM We know that Java is a static language, while Python and Ruby are dynamic languages. Once a Java program is written, it is difficult to change the class behavior at runtime, while Python and Ruby can. However, on the bytecode layer, we can do some work to make Java programs more flexible and magic. ASM is such an open-source library that is widely used. ASM is a Java bytecode manipulation framework. It can be used to dynamically generate stub classes or other proxy classes, Directly in binary form, or to dynamically modify classes at load time, I. e., just before they are loaded into the Java Virtual Machine. ASM completes the same functionality of bcel and serp, but ASM Only over 30 K, and the latter two are 150 K and K respectively. Apache is becoming increasingly popular. Let's take a look at a simple example of ASM helloworld. Java, which generates an example class and a main method. The main method prints "Hello world! "Statement: Code
- Import java. Io. fileoutputstream;
- Import java. Io. printstream;
- Import org. objectweb. ASM. classwriter;
- Import org. objectweb. ASM. methodvisitor;
- Import org. objectweb. ASM. Opcodes;
- Import org. objectweb. ASM. type;
- Import org. objectweb. ASM. commons. generatoradapter;
- Import org. objectweb. ASM. commons. method;
- Public class helloworld extends classloader implements Opcodes {
- Public static void main (final string ARGs []) throws exception {
- // Creates a classwriter for the example public class,
- // Which inherits from object
- Classwriter CW = new classwriter (0 );
- CW. Visit (v1_1, acc_public, "example", null, "Java/lang/object", null );
- Methodvisitor Mw = CW. visitmethod (acc_public, "<init>", "() V", null,
- Null );
- MW. visitvarinsn (aload, 0 );
- MW. visitmethodinsn (invokespecial, "Java/lang/object", "<init>", "() V ");
- MW. visitinsn (return );
- MW. visitmaxs (1, 1 );
- MW. visitend ();
- Mw = CW. visitmethod (acc_public + acc_static, "Main ",
- "([Ljava/lang/string;) V", null, null );
- MW. visitfieldinsn (getstatic, "Java/lang/system", "out ",
- "Ljava/IO/printstream ;");
- MW. visitldcinsn ("Hello world! ");
- MW. visitmethodinsn (invokevirtual, "Java/IO/printstream", "println ",
- "(Ljava/lang/string;) V ");
- MW. visitinsn (return );
- MW. visitmaxs (2, 2 );
- MW. visitend ();
- Byte [] code = CW. tobytearray ();
- Fileoutputstream Fos = new fileoutputstream ("example. Class ");
- FOS. Write (CODE );
- FOS. Close ();
- Helloworld loader = new helloworld ();
- Class exampleclass = Loader
- . Defineclass ("example", code, 0, code. Length );
- Exampleclass. getmethods () [0]. Invoke (null, new object [] {null });
- //------------------------------------------------------------------------
- // Same example with a generatoradapter (more convenient but slower)
- //------------------------------------------------------------------------
- CW = new classwriter (classwriter. compute_maxs );
- CW. Visit (v1_1, acc_public, "example", null, "Java/lang/object", null );
- Method M = method. getmethod ("Void <init> ()");
- Generatoradapter Mg = new generatoradapter (acc_public, M, null, null,
- CW );
- MG. loadthis ();
- MG. invokeconstructor (type. GetType (object. Class), M );
- MG. returnvalue ();
- MG. endmethod ();
- M = method. getmethod ("Void main (string [])");
- Mg = new generatoradapter (acc_public + acc_static, M, null, null, Cw );
- MG. getstatic (type. GetType (system. Class), "out", Type
- . GetType (printstream. Class ));
- MG. Push ("Hello world! ");
- MG. invokevirtual (type. GetType (printstream. Class), Method
- . Getmethod ("Void println (string )"));
- MG. returnvalue ();
- MG. endmethod ();
- CW. visitend ();
- Code = CW. tobytearray ();
- Loader = new helloworld ();
- Exampleclass = loader. defineclass ("example", code, 0, code. Length );
- Exampleclass. getmethods () [0]. Invoke (null, new object [] {null });
- }
- }
We can see that the above example uses methods of ASM methodvisitor and generatoradapter to dynamically generate the example class and call the print statement.
Iv. cglib Cglib is a powerful, high performance and quality code generation library, it is used to extend Java classes and implements interfaces at runtime. Cglib is the abbreviation of code generation library. Cglib depends on the ASM library. Hibernate uses cglib to generate pojo subclasses and override get to implement the lazy loading mechanism. Spring uses cglib to implement dynamic proxy. The dynamic proxy mechanism of JDK requires an interface, which forces our pojo to implement an interface. Here is an entry-level example of cglib: Myclass. Java: Code
- Public class myclass {
- Public void print (){
- System. Out. println ("I'm in myclass. Print! ");
- }
- }
Main. Java: Code
- Import java. Lang. Reflect. method;
- Import net. SF. cglib. Proxy. enhancer;
- Import net. SF. cglib. Proxy. methodinterceptor;
- Import net. SF. cglib. Proxy. methodproxy;
- Public class main {
- Public static void main (string [] ARGs ){
- Enhancer = new enhancer ();
- Enhancer. setsuperclass (myclass. Class );
- Enhancer. setcallback (New methodinterceptorimpl ());
- Myclass my = (myclass) enhancer. Create ();
- My. Print ();
- }
- Private Static class methodinterceptorimpl implements methodinterceptor {
- Public object intercept (Object OBJ, method, object [] ARGs,
- Methodproxy proxy) throws throwable {
- // Log something
- System. Out. println (method + "intercepted! ");
- Proxy. invokesuper (OBJ, argS );
- Return NULL;
- }
- }
- }
The printed result is: Code
- Public void myclass. Print () Intercepted!
- I'm in myclass. Print!
This example basically implements the log AOP function. |
|