Dynamic Agent Overview
When I was learning spring, I learned that using dynamic proxies to implement AOP is an introduction: you need to calculate the call time for all methods. It is possible to get the current time for each method start and end. Similar to this:
long current=system.currenttimemillis (); Call the original method long last=system.currenttimemillis ();
If each method is actually a bit uncomfortable to join, the dynamic agent appeared. The dynamic proxy rewrites the sub-code of the original corresponding class by using the bytecode technique, and adds the corresponding logic.
Mainstream dynamic agent implementation techniques are as follows: JDK and Cglib,javassist,asm refer to this.
Application of MyBatis
We know that in MyBatis, we just write the Mapper interface and interface corresponding to the Mapper.xml, use the following method to get the instance and call method. (code from MYBATIS3 comes with test cases)
Boundblogmapper mapper = Session.getmapper (boundblogmapper. Class);
Blog B = mapper.selectblogwithpostsusingsubselect (1);
Assertequals (1, B.getid ());
Session.close ();
The mapper in this is the object of the proxy class that gets the interface boundblogmapper using the dynamic proxy method in the JDK. Concrete ways to see for yourself. Very easy to track. The most important thing about JDK dynamic agent is to implement
the processing of the Invocationhandler interface is tiring. The most severe calls are as follows. the most important Mappermethod.execute (sqlsession, args) in the Invoke method
1 Public classMapperproxy<t>ImplementsInvocationhandler, Serializable {2 3 Private Static Final LongSerialversionuid = -6424540398559729838l;4 Private Finalsqlsession sqlsession;5 Private FinalClass<t>Mapperinterface;6 Private FinalMap<method, mappermethod>Methodcache;7 8 PublicMapperproxy (sqlsession sqlsession, class<t> mapperinterface, Map<method, mappermethod>Methodcache) {9 This. sqlsession =sqlsession;Ten This. Mapperinterface =Mapperinterface; One This. Methodcache =Methodcache; A } - - PublicObject Invoke (Object proxy, Method method, object[] args)throwsThrowable { the if(Object.class. Equals (Method.getdeclaringclass ())) { - Try { - returnMethod.invoke ( This, args); -}Catch(Throwable t) { + Throwexceptionutil.unwrapthrowable (t); - } + } A FinalMappermethod Mappermethod =Cachedmappermethod (method); at returnMappermethod.execute (sqlsession, args); - } - - PrivateMappermethod Cachedmappermethod (method) { -Mappermethod Mappermethod =Methodcache.get (method); - if(Mappermethod = =NULL) { inMappermethod =NewMappermethod (Mapperinterface, Method, Sqlsession.getconfiguration ()); - Methodcache.put (method, Mappermethod); to } + returnMappermethod; - } the *}
Different processing according to several types of operation
PublicObject Execute (sqlsession sqlsession, object[] args) {object result; if(Sqlcommandtype.insert = =Command.gettype ()) {Object param=Method.convertargstosqlcommandparam (args); Result=Rowcountresult (Sqlsession.insert (Command.getname (), param)); } Else if(Sqlcommandtype.update = =Command.gettype ()) {Object param=Method.convertargstosqlcommandparam (args); Result=Rowcountresult (Sqlsession.update (Command.getname (), param)); } Else if(Sqlcommandtype.delete = =Command.gettype ()) {Object param=Method.convertargstosqlcommandparam (args); Result=Rowcountresult (Sqlsession.delete (Command.getname (), param)); } Else if(Sqlcommandtype.select = =Command.gettype ()) { if(Method.returnsvoid () &&Method.hasresulthandler ()) {Executewithresulthandler (sqlsession, args); Result=NULL; } Else if(Method.returnsmany ()) {result=Executeformany (sqlsession, args); } Else if(Method.returnsmap ()) {result=Executeformap (sqlsession, args); } Else{Object param=Method.convertargstosqlcommandparam (args); Result=Sqlsession.selectone (Command.getname (), param); } } Else if(Sqlcommandtype.flush = =Command.gettype ()) {Result=sqlsession.flushstatements (); } Else { Throw NewBindingexception ("Unknown execution method for:" +command.getname ()); } if(Result = =NULL&& Method.getreturntype (). isprimitive () &&!method.returnsvoid ()) { Throw NewBindingexception ("Mapper method" +Command.getname ()+ "attempted to return null from a method with a primitive return type (" + method.getreturntype () + ")."); } returnresult; }
MyBatis Source Learning: Application of dynamic agent (slowly change)