The use and principle analysis of mapper mapping configuration in <mybatis framework above (vi) mapperregistry> We know the Getmapper method of Defaultsqlsession, Finally, the mapper instance is obtained through the Mapperregistry object:
Public<T> T Getmapper (class<t>type, sqlsession sqlsession) { FinalMapperproxyfactory<t> mapperproxyfactory = (mapperproxyfactory<t>) Knownmappers.get (type); if(Mapperproxyfactory = =NULL) { Throw NewBindingexception ("type" + Type + "is not known to the Mapperregistry.")); } Try { returnmapperproxyfactory.newinstance (sqlsession); } Catch(Exception e) {Throw NewBindingexception ("Error getting mapper instance. Cause: "+e, E); } }
From the code we see an attempt to remove mapperproxyfactory from a variable called knownmappers.
Let's look at the definition of this knownmapper in Mapperregistry:
Private Final New Hashmap<class<?>, mapperproxyfactory<?>> ();
There are getmapper methods, then the inevitable Addmapper method:
Public<T>voidAddmapper (class<t>type) { if(Type.isinterface ()) {if(Hasmapper (type)) {Throw NewBindingexception ("type" + Type + "is already known to the Mapperregistry."); } Booleanloadcompleted =false; Try{knownmappers.put (type,NewMapperproxyfactory<t>(type)); //It's important that the type was added before the parser is run//otherwise the binding may automatically is attempted by the//Mapper parser. If the type is already known, it won ' t try. Mapperannotationbuilder parser =Newmapperannotationbuilder (config, type); Parser.parse (); LoadCompleted=true; } finally { if(!loadcompleted) {knownmappers.remove (type); } } } }
Use and principle analysis of mapper mapping configuration in <mybatis Framework (iv) Parsing mapper interface map XML file > Article, parsing after playing XML, binding namespace Bindmapperfornamespace () method
//Binding to namespacesPrivate voidBindmapperfornamespace () {String namespace=Builderassistant.getcurrentnamespace (); if(Namespace! =NULL) {Class<?> Boundtype =NULL; Try{Boundtype=Resources.classforname (namespace); } Catch(ClassNotFoundException e) {//Ignore, bound type is not required } if(Boundtype! =NULL) { if(!Configuration.hasmapper (Boundtype)) { //Spring may isn't know the real resource name so we set a flag//To prevent loading again this resource from the Mapper interface//Look at mapperannotationbuilder#loadxmlresourceConfiguration.addloadedresource ("namespace:" +namespace); Configuration.addmapper (Boundtype); } } }}
We see
Configuration.addmapper (Boundtype);
Just call the Mapperregistry.addmapper method
Public void addmapper (class<t> type) { mapperregistry.addmapper (type); }
We look back at how Getmapper gets the Mapper object:
1. Get mapperproxyfactory First
2. Call the Newinstance method of the Mapperproxyfactory object to get the mapper.
Let's look at the Mapperproxyfactory code:
Public T newinstance (sqlsession sqlsession) { finalnew mapperproxy<t>(sqlsession , Mapperinterface, Methodcache); return newinstance (mapperproxy); } protected T newinstance (mapperproxy<t> mapperproxy) { returnnew class[] { Mapperinterface}, Mapperproxy);
This is the return of a proxy class instance mapperproxy.
Packageorg.apache.ibatis.binding;Importjava.io.Serializable;ImportJava.lang.reflect.InvocationHandler;ImportJava.lang.reflect.Method;ImportJava.util.Map;ImportOrg.apache.ibatis.reflection.ExceptionUtil;Importorg.apache.ibatis.session.SqlSession;/** * @authorClinton Begin *@authorEduardo Macarron*/ Public classMapperproxy<t>ImplementsInvocationhandler, Serializable {Private Static Final LongSerialversionuid = -6424540398559729838l; Private Finalsqlsession sqlsession; Private FinalClass<t>Mapperinterface; Private FinalMap<method, mappermethod>Methodcache; PublicMapperproxy (sqlsession sqlsession, class<t> mapperinterface, Map<method, mappermethod>Methodcache) { This. sqlsession =sqlsession; This. Mapperinterface =Mapperinterface; This. Methodcache =Methodcache; } PublicObject Invoke (Object proxy, Method method, object[] args)throwsThrowable {if(Object.class. Equals (Method.getdeclaringclass ())) { Try { returnMethod.invoke ( This, args); } Catch(Throwable t) {Throwexceptionutil.unwrapthrowable (t); } } FinalMappermethod Mappermethod =Cachedmappermethod (method); returnMappermethod.execute (sqlsession, args); } PrivateMappermethod Cachedmappermethod (method) {Mappermethod Mappermethod=Methodcache.get (method); if(Mappermethod = =NULL) {Mappermethod=NewMappermethod (Mapperinterface, Method, Sqlsession.getconfiguration ()); Methodcache.put (method, Mappermethod); } returnMappermethod; }}
To use a dynamic agent for Java, you have to implement the Invocationhandler interface:
@Override PublicObject Invoke (Object proxy, Method method, object[] args)throwsThrowable {Try { if(Object.class. Equals (Method.getdeclaringclass ())) { returnMethod.invoke ( This, args); } Else if(Isdefaultmethod (method)) {returnInvokedefaultmethod (proxy, method, args); } } Catch(Throwable t) {Throwexceptionutil.unwrapthrowable (t); } FinalMappermethod Mappermethod =Cachedmappermethod (method); returnMappermethod.execute (sqlsession, args); }
The first thing to judge is whether the proxy object is an interface or a class, and obviously we do not have any implementation of the Mapper interface, then it will execute
Final Mappermethod Mappermethod = Cachedmappermethod (method); return mappermethod.execute (sqlsession, args);
Generates a Mappermethod object, then calls its Execute method, passes the sqlsession and arguments in, executes the Mapper method.
Use and principle analysis of mapper mapping configuration in MyBatis Framework (vii) Mapperproxy,mapperproxyfactory