The Codeinjector of Javassist Universal tools

Source: Internet
Author: User

The Codeinjector of Javassist Universal tools

You are currently working on an APM project to modify the code at run time. There are several tools commonly used for modification: ASM, BCEL, Javassist. By contrast, Javassist was used in the project.

See this article, need to have a certain understanding of Javassist, you can refer to: Javassist:quick Start

In the process of using javassist, the most common method is the insertbefore,insertafter,addcatch of Ctmethod (or Ctconstructor), There is another kind of injectaround (which needs to be done by itself). Refer to: Spring:aop before after Afterreturn afterthrowing around principle

The concept of before,beforearound,beforeafter,beforethrowing,beforereturning is introduced in the code, and is used in the spring AOP configuration.

 Packageorg.fjn.frameworkex.javassist;Importjavassist. Ctclass;Importjavassist. Ctconstructor;Importjavassist. Ctmethod;Importjavassist. Ctnewmethod;/*** Code Inject Tool * *@author<a href= "Mailto:[email protected]" >[email protected]</a> **/ Public classCodeinjector { Public Static FinalString Method_ruturn_value_var = "__fjn__result";  Public Static FinalString Method_exec_exception_var = "Ex";  Public Static FinalString constructor_delegate_prefix = "__fjn__doc__";  Public Static FinalString method_delegate_prefix = "__fjn__dom__";  Public Static FinalString PROCEED = "$proceed";  Public Static FinalString CRLF = "\ n";  Public Static FinalString crlf_tab = "\n\t";  Public Static FinalString crlf_2tab = "\n\t\t";  Public Static FinalString crlf_3tab = "\n\t\t\t";  Public Static FinalString crlf_4tab = "\n\t\t\t\t";  Public Static Finalstring Getdelegatemethodnameofconstructor (String constructorname) {returnConstructor_delegate_prefix +Constructorname; }     Public Static Finalstring Getdelegatemethodnameofmethod (String methodName) {returnMethod_delegate_prefix +MethodName; }    /*** Inject around code to the specified method * *@see#injectInterceptor (Ctclass, Ctmethod, String, String, String, * string, String)*/     Public voidInjectaround (Ctmethod method, String Beforearound, String afteraround, String afterthrowing, String Afterr eturning)throwsException {ctclass clazz=Method.getdeclaringclass ();    Injectaround (Clazz, method, Beforearound, Afteraround, afterthrowing, afterreturning); }    /*** Inject around code to the specified method * *@see#injectInterceptor (Ctclass, Ctmethod, String, String, String, * string, String)*/     Public voidInjectaround (Ctclass clazz, Ctmethod method, String Beforearound, String afteraround, String afterthrowing , String afterreturning)throwsException {injectinterceptor (Clazz, method,NULL, Beforearound, Afteraround, afterthrowing, afterreturning); }    /*** Inject around code to the specified method * * <pre> * <code> * <span style= "fo nt-size:12px; Color:green; " >before block ... </span> * try{* <span style= "font-size:12px; color:green;"     >beforearound block ... </span> * $procced ($$); * <span style= "FONT-SIZE:12PX; Color:green; " >afteraround block ... </span> *}catch (Throwable ex) {* <span style= "FONT-SIZE:12PX; color:green ;" >afterthrowing block ... </span> *}finally{* <span style= "font-size:12px; color:green;" >afterreturning block ... </span> *} * </code> * </pre> **/     Public voidInjectinterceptor (Ctclass clazz, Ctmethod method, string before, String Beforearound, String afteraround, String afterthrowing, String afterreturning)throwsException {clazz.defrost (); intmodifiers =method.getmodifiers (); Ctclass ReturnType=Method.getreturntype (); ctclass[] Parameters=method.getparametertypes (); Ctclass[] Exceptions=method.getexceptiontypes (); String MethodName=Method.getname (); String Delegatemethod=Getdelegatemethodnameofmethod (methodName);        Method.setname (Delegatemethod); StringBuilder Buffer=NewStringBuilder (256); BooleanHasreturnvalue = (Ctclass.voidtype = =returntype); Buffer.append ("{" +crlf_tab); {            if(hasreturnvalue) {String Returnclass=Returntype.getname (); Buffer.append (Returnclass+ "" + Method_ruturn_value_var + ";"); }            if(Before! =NULL) {buffer.append (before);            } buffer.append (Crlf_tab); Buffer.append ("Try {" +crlf_2tab); {                if(Beforearound! =NULL) {buffer.append (beforearound);                } buffer.append (Crlf_2tab); if(hasreturnvalue) {buffer.append (Method_ruturn_value_var+ "= ($r)" + Delegatemethod + "($$);"); } Else{buffer.append (Delegatemethod+ "($$);"); }                if(Afteraround! =NULL) {buffer.append (crlf_2tab);                Buffer.append (Afteraround); }                if(hasreturnvalue) {buffer.append (crlf_2tab); Buffer.append ("Return" +Method_ruturn_value_var);            }} buffer.append (Crlf_tab); Buffer.append ("} catch (Throwable ex) {");                {buffer.append (Crlf_2tab); if(Afterthrowing! =NULL) {buffer.append (afterthrowing);                } buffer.append (Crlf_2tab); Buffer.append ("Throw ex;");            } buffer.append (Crlf_tab); Buffer.append ("}"); if(Afterreturning! =NULL) {buffer.append (crlf_tab); Buffer.append ("Finally {");                    {buffer.append (Crlf_2tab);                Buffer.append (afterreturning);                } buffer.append (Crlf_tab); Buffer.append ("}");        }} buffer.append (CRLF); Buffer.append ("}"); System.out.println (MethodName+ "'ll be modified as: \ n" +buffer.tostring ()); Ctmethod Newmethod=Ctnewmethod.make (modifiers, returntype, methodName, parameters, exceptions, buffer.tostring (), clazz);    Clazz.addmethod (Newmethod); }    /*** Inject around code to the specified constructor * *@see#injectAround (Ctclass, Ctconstructor, String, String, String, * string)*/     Public voidInjectaround (Ctconstructor constructor, String beforearound, String afteraround, String afterthrowing, Str ing afterreturning)throwsException {ctclass clazz=Constructor.getdeclaringclass ();    Injectaround (Clazz, constructor, Beforearound, Afteraround, afterthrowing, afterreturning); }    /*** Inject around code to the specified constructor * * <pre> * <code> * try{* <span style= "FONT-SIZE:12PX; Color:green; "     >beforearound block ... </span> * $procced ($$); * <span style= "FONT-SIZE:12PX; Color:green; " >afteraround block ... </span> *}catch (Throwable ex) {* <span style= "FONT-SIZE:12PX; color:green ;" >afterthrowing block ... </span> *}finally{* <span style= "font-size:12px; color:green;" >afterreturning block ... </span> *} * </code> * </pre> **/     Public voidInjectaround (Ctclass Clazz, Ctconstructor constructor, String beforearound, String afteraround, string aft Erthrowing, String afterreturning)throwsException {clazz.defrost (); String Delegatemethodname=Getdelegatemethodnameofconstructor (Constructor.getname ()); Ctmethod Delegatemethod=Constructor.tomethod (Delegatemethodname, clazz);        Clazz.addmethod (Delegatemethod);        Injectaround (Clazz, Delegatemethod, Beforearound, Afteraround, afterthrowing, afterreturning); Constructor.setbody ("{" + PROCEED + "($$);", "This", Delegatemethodname); }    /*** Copy form the SRC method's body to a Overrid method's body in Target * class. *      * @paramTargetclass * Overrid The method in the target class *@paramSrcmethod * The Overrid from would copy from the SRC method.  If the target * class has a not owner Overrid method, you should specified the * Srcmethod in     The Super class. * @paramBody * The body of the override method *@paramDelegateobject * The delegate object default value is ' this '. * @paramDelegatemethod *@throwsException*/     Public voidOverridemethod (Ctclass targetclass, Ctmethod Srcmethod, String body, String delegateobject, String Delegat Emethod)throwsException {targetclass.defrost ();        System.out.println (body); if(Delegateobject = =NULL) {Delegateobject= "This"; }        //override method in a super class of the target class        if(Srcmethod.getdeclaringclass ()! =Targetclass) {Ctmethod Destmethod= Ctnewmethod.copy (Srcmethod, Targetclass,NULL); if(Body! =NULL&&!Body.isempty ()) {                if(Delegatemethod! =NULL&&!Delegatemethod.isempty ())                {Destmethod.setbody (body, delegateobject, Delegatemethod); } Else{destmethod.setbody (body);        }} targetclass.addmethod (Destmethod); }        //override method in the target class        Else {            if(Delegatemethod! =NULL&&!Delegatemethod.isempty ())            {Srcmethod.setbody (body, delegateobject, Delegatemethod); } Else{srcmethod.setbody (body); }        }    }}

Injectinterceptor () Implementation principle: The original method is renamed to a Delegatemethod, re-create a target method, the body is to weave code, and call Delegatemethod.

Injectaround (Ctconstrouctor) Implementation principle: First, the content of the structure is extracted into a delegatemethod, and then the Delegatemethod do the weaving, and finally set up a new build body. Call Delegatemethod in the new constructor.


The Codeinjector of Javassist Universal tools

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.