When defining a Mapper interface (Userdao), we do not need to implement this class, but Sqlsession.getmapper () eventually returns an object that implements the interface. This object is implemented by MyBatis using the dynamic proxy of JDK. Here we will introduce the generation process of this proxy object and the implementation process of its method. The mapper code object's build Process Defaultsqlsession.getmapp () method will eventually invoke the Mapperregistry.getmapper () method [java] View Plain copy Public <t> t getmapper (class<t> type, sqlsession sqlsession) { //This mapperproxyfactory is the, that is added to the knownmappers when the Addmapper method is invoked. final MapperProxyFactory<T> mapperProxyFactory = (mapperproxyfactory<t>) knownmappers.get (type); if (mapperproxyfactory == null) //indicates that the Mapper interface is not registered throw new bindingexception ("type " + type + " is not known To the mapperregistry. "); try { //generates a Mapperproxy object return Mapperproxyfactory.newinstance (sqlsession); } catch (exception e) { throw new bindingexception ("error getting mapper instance. Cause: " + e, e); } } Below is the Newinstance method of mapperproxyfactory [java] view plain copy public t Newinstance (sqlsession sqlsession) { //creates a Mapperxy object, This method implements the Invocationhandler interface in the JDK dynamic proxy final MapperProxy<T> Mapperproxy = new mapperproxy<t> (Sqlsession, mapperinterface, methodcache); return newinstance (mapperproxy); } protected t newinstance (mapperproxy<t> mapperproxy) { // Mapperinterface, the Mapper interface is represented, the object returned is a subclass of the Mapper interface, and the method is called to be Mapperproxy intercepted, that is, to execute the Mapperproxy.invoke () method return (T) proxy.newproxyinstance (Mapperinterface.getclassloader (), new class[] { mapperinterface }, mapperproxy); } Mapperproxy Detailed analysis Mapperproxy [java] view plain copy public class mapperproxy<t>& nbsp;implements invocationhandler, serializable { private static final long serialVersionUID = -6424540398559729838L; private final SqlSession sqlSession; //mapper Interface private final Class<T> mapperInterface; //mapper each square in the interfaceThe FA will generate a Mappermethod object, methodcache maintain their correspondence // This methodcache is held in Mapperproxyfactory, Mapperproxyfactory is held in configuration // So each mapper interface class corresponding to the Mapperproxyfactory and Methodcache is shared throughout the application, and generally there will only be one instance private final Map<Method, MapperMethod> methodCache; public Mapperproxy (sqlsession sqlsession, class<t> mapperinterface, map<method, Mappermethod> methodcache) { this.sqlSession = sqlsession; this.mapperinterface = mapperinterface; this.methodcache = methodCache; } //This will intercept the Mapper interface ( Userdao) of all Methods public object invoke (ObJect proxy, method method, object[] args) throws Throwable { //If it is a method defined in object, execute directly. such as ToString (), hashcode () wait. if (Object.class.equals (Method.getdeclaringclass ()) { try { return method.invoke (This, args); } catch (throwable t) { throw Exceptionutil.unwrapthrowable (t); } } //Other methods of Mapper interface definition are assigned to Mappermethod for execution. final mappermethod mappermethod = cachedmappermethod ( method); return mappermethod.execute (sqlsesSion, args); } private MapperMethod Cachedmappermethod (Method method) { MapperMethod Mappermethod = methodcache.get (method); if (Mappermethod == null) { mapperMethod = new Mappermethod (Mapperinterface, method, sqlsession.getconfiguration ()); methodcache.put (Method, mappermethod); } return mapperMethod; } }
Mappermethod [java] View Plain copy//All Mapper interfaces The method is invoked, and this method is executed. This is actually a method to invoke sqlsession Public object execute (Sqlsession sqlsession, object[] args) { Object result; //This method is judged by the SQL type in the annotation if ( Sqlcommandtype.insert == command.gettype ()) { //Execute INSERT object param = method.convertargstosqlcommandparam (args); result = rowcountresult (Sqlsession.insert (Command.getname), param); } else if (sqlcommandtype.update == Command.gettype ()) { //Executive update Object param = method.convertargstosqlcommandparam (args); Result = rowcountresuLt (Sqlsession.update (Command.getname (), param)); } else if ( Sqlcommandtype.delete == command.gettype ()) { /delete object param = method.convertargstosqlcommandparam (args); result = rowcountresult (Sqlsession.delete (Command.getname (), param); } else if (Sqlcommandtype.select == command.gettype ()) ) { //select , query if ( Method.returnsvoid () && method.hasresulthandler ()) { //has no return value and has Resulthandler Executewithresulthandler (Sqlsession, args); result = null; } else if (Method.returnsmany ()) { / /Return to a list result = executeformany (sqlSession, args); } else if (Method.returnsmap ()) { //returns a map result = executeformap (Sqlsession, args); } else { //returns an object object param = method.convertargstosqlcommandparam (args); result = sqlsession.selectone (Command.getname (), param); } } else { throw new bindingexception (" unknown execution method for: " + command.getname ()); } if (Result == null && method.getreturntype (). Isprimitive () && !method.returnsvoid ()) { throw new Bindingexception ("mapper method '" + command.getname () + " attempted to return null from a method with a primitive return type (" + method.getreturntype () + ")."); } return result; }
Summary in the programming interface provided by MyBatis, developers need only define mapper interfaces (such as: Userdao), which developers do not need to implement. MyBatis uses JDK's dynamic proxies to implement the Mapper interface. In MyBatis, each mapper interface corresponds to a Mapperproxyfactory object instance, which corresponds to the Configuration.mapperRegistry.knownMappers. When the Getmapper () method is invoked, MyBatis finds the corresponding Mapperproxyfactory object instance, using the factory to create a JDK dynamic proxy object, which is the implementation class for this mapper interface, when the method defined by mapper is invoked, Will invoke Mapperproxy to process it. Mapperproxy will find the corresponding Mappermethod object according to the method to implement this call. The mappermethod corresponds to the annotation in the method, the corresponding Mappedstatement object is found from the configuration, and then executed.