"Mybtais" Mybatis plug-in plugin development (a) dynamic agent step-by-step analysis

Source: Internet
Author: User

Demand:

The methods in the original system are ' intercepted ' to add new processing logic before and after the method is executed.

Analysis:

The way to do this is to make changes to each of the original methods, add new logic, and if you need to intercept fewer methods, choosing this method will save you money. But what about hundreds of thousands of ways? A dynamic proxy is required to implement this.

Scene:

For example: Add logging to the original system, add performance analysis, etc...

Example:

as follows, you need to "intercept" the sleep method of the Sleep object and add new logic before and after the method's execution. Want to know, ' What did you do before you went to bed? What did you do after bed? ’

Interface Sleep {    publicvoid  sleep ();}
 public  class   Sleepimpl implements sleep{ public  void   sleep () {System.  out . println ( "  I'm on   " +new  simpledateformat ("  yyyy-mm-dd hh:mm   " ). Format (new  Date ()) + "  start sleeping   " 

Create a dynamic proxy class to implement the Invocationhandler interface. The following wrap method: Incoming object to be proxied by Target. Returns the wrapped proxy object. $Proxy break point will see such an object. For the following Sleepproxy object, Sleepproxy.sleep () calls the method that needs to be intercepted. The Invoke method in plugin is actually called. The Method.invoke (Target,args) in the Invoke method is really the sleep method that invokes the Proxied object. Therefore, directly before and after this statement to add the appropriate logic to meet the needs.

 Public classPlugin implements Invocationhandler {PrivateObject Target; Plugin (Object target) { This. target =Target; }         Publicobject Invoke (Object proxy, Method method, object[] args) throws Throwable {//things to do before you go to bedObject result =Method.invoke (target, args); //things to do after bed        returnresult; }         Public StaticObject Wrap (object target) {returnproxy.newproxyinstance (Target.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), NewPlugin (target)); }}
 Public class Main {    publicstaticvoid  main (string[] args) {        // the object        to be proxied New Sleepimpl ();         // proxy Object        Sleep Sleepproxy = (sleep) plugin.wrap (sleep);        Sleepproxy.sleep ();    }}

So you think it's over? No, this is just about what you did before and after you went to bed, and you want to know what you ate before and after your bedtime? Of course, eating after sleeping a little to say. But the tacit will. There are other Balabala needs as well. What are you going to do? Do you want to put all the new logic in the method plugin the Invoke method? That's not appropriate! Disorderly mess like this. Then can we abstract out an interception interface in which there is a way to do what after interception. A variety of requirements only need to implement this interception interface can!

Interface Interceptor {    publicvoid  Interceptbefore () throws Exception;          Public void Interceptafter () throws Exception;}
 Public class Sleepbeforeandafter implements Interceptor {    publicvoid  Interceptbefore () throws Exception {        System. out. println (" before ... ");    }      Public void Interceptafter () throws Exception {        System. out. println (" after ... ");            }}

Then the dynamic proxy class plugin needs to be modified

/** * Dynamic Agent * * @author Wei Shendi * October 13, 2018*/ Public classPlugin implements Invocationhandler {PrivateObject Target; PrivateList<interceptor> iList =NewArraylist<interceptor>(); Plugin (Object target, List<Interceptor>iList) {         This. target =Target;  This. iList =iList; }         Publicobject Invoke (Object proxy, Method method, object[] args) throws Throwable { for(Interceptor I:ilist) {I.interceptbefore (); } Object result=Method.invoke (target, args);  for(Interceptor I:ilist) {i.interceptafter (); }        returnresult; }         Public StaticObject Wrap (Object target,list<interceptor>iList) {        returnproxy.newproxyinstance (Target.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), NewPlugin (target,ilist)); }}
 Public class Main {    publicstaticvoid  main (string[] args) {        new Sleepimpl ();        ListNew arraylist<interceptor>();        Ilist.add (new  sleepbeforeandafter ());         = (Sleep) plugin.wrap (sleep,ilist);        Sleepproxy.sleep ();    }}

Now want to intercept each object's methods, directly implement the Interceptor interface can be! Implement two of these methods. At this point our new logic and the original logic do not have any intersection. What if we want to use the various properties of the Proxied object in the two methods in interceptor? The first thought was to add parameters to the two methods of the Interceptor interface.

 Public classSleepbeforeandafter implements Interceptor { Public voidInterceptbefore (Object target, method method, object[] args) throws Exception {System. out. println ("before ... Interceptbefore (Object target, method method, object[] args)"); }     Public voidInterceptafter (Object target, method method, object[] args) throws Exception {System. out. println ("after ... Interceptafter (Object target, method method, object[] args)"); }}

In this case, the personal feeling is no problem "Daniel, if found clearly inconsistent, please point out." But but we ran a simple, object-oriented idea (in fact, MyBatis source plug-in design). We are making further streamlining. So the invocation object was produced. See the method object passed in. Is it possible to think that we are no longer calling Method.invoke (Target,args) in the Invoke method in plugin, but rather in intercetpor after the logic has been processed and then called. This division of labor is clear.

/** * Block Object Packaging * @author Wei Shendi * October 13, 2018*/ Public classInvocation {PrivateObject Target; PrivateObject []args; Privatemethod method; Invocation (Object Target,method method,object[] args) { This. target =Target;  This. args =args;  This. method =method; }    /** * The corresponding method to execute the Interception object * @return * @throws Exception*/     PublicObject process () throws exception{returnMethod.invoke (target, args); }    }

Now, the interceptor interceptor should be like this.

Interface Interceptor {    public  Object intercept (invocation invocation) throws Exception;}
 Public class Sleepbeforeandafter implements Interceptor {    public  Object intercept (invocation invocation ) throws exception{        System. out. println (" before the method to be executed to intercept the sleep method ");         = invocation.process ();        System. out. println (" after the method to be executed to intercept the sleep method ");         return result;}    }

Plugin should be like this at this point.

 Public classPlugin implements Invocationhandler {PrivateObject Target; PrivateInterceptor Interceptor; Plugin (Object Target,interceptor Interceptor) { This. target =Target;  This. Interceptor =Interceptor; }         Publicobject Invoke (Object proxy, Method method, object[] args) throws Throwable {Invocation INV Ocation=Newinvocation (Target,method,args); returninterceptor.intercept (invocation); }         Public StaticObject Wrap (Object Target,interceptor Interceptor) {returnproxy.newproxyinstance (Target.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), NewPlugin (target,interceptor)); }}
 Public class Main {    publicstaticvoid  main (string[] args) {        new Sleepimpl ();         New Sleepbeforeandafter ();         = (Sleep) plugin.wrap (sleep,s);        Sleepproxy1.sleep ();         = (Sleep) plugin.wrap (sleepProxy1, s);        Sleepproxy2.sleep ();    }}

To this, MyBatis plug-in development of the introduction is complete! In fact, the use of dynamic agents and the combination of responsibility chain way.

  

"Mybtais" Mybatis plug-in plugin development (a) dynamic agent step-by-step analysis

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.