KeyWords: Mybatis Principles, Source Code, Mybatis Mapper Interface Implementation Classes, Proxy Patterns, Dynamic Proxies, Java Dynamic Proxies, Proxy.newProxyInstance, Mapper Mapper, Mapper Implementations
MyBatis is an excellent persistence layer framework that supports customized SQL, stored procedures, and advanced mapping. MyBatis is an excellent persistence layer framework with support for custom SQL, stored procedures, and advanced mappings. myBatis avoids almost all of the JDBC code and manual setting of parameters and getting result sets. We use Mybaits for , usually just need to define a few Mapper interfaces , and then write an xml file , we write the sql in the configuration file , Mybatis help us to complete the specific implementation of the Mapper interfaces to call . As well as mapping the results to the model bean.
We wrote in the project in the many Mapper class is just an interface (interface ), according to Java's polymorphism, we know that you can use the interface interface as a formal parameter, and then at runtime to determine the specific implementation of the object is what. However, for the Mapper interface, we have not written its implementation class! How does Mybatis find its implementation class, and then complete the specific CRUD method calls? How does Mybatis find its implementation class to make specific CRUD method calls?
In order to figure out how the Mapper interface finds its implementation class, let's recall how Mybatis uses it, based on real examples, and then analyze it a little bit. The use here refers to the use of Mybatis alone, rather than integrating spring , because the integration of spring , you also need to involve the Mapper dao loaded into the spring container , spring to help create the data source configuration and other issues.
Typically, the main steps in using Mybatis are:
Starting with a piece of code
Above, we summarized the 4 steps in using Mybatis. These 4 steps look simple, but writing them out in code is a lot. We might as well memorize these 4 steps before going through the code, it will be easier.
In this piece of code, part 1 we used Java coding to implement the SqlSessionFactory, or we could have used xml. If we use xml, the first part of the code above looks like this:
Our goal this time is to figure out " how Mapper finds the implementation class ", we note the location of the code 3 , 4 above:
Here mapper can call selectBlog( 1) this method, indicating that mapper is an object, because the object only has method behavior implementation ah. BlogMapper interface can not be instantiated, much less specific method implementation. We don't define a class that implements the BlogMapper interface, we just call session.getMapper(). From this, we can deduce that it must be the session.getMapper() method that internally generates the implementation class of BlogMapper. What techniques are available to generate an implementation class based on the BlogMapper interface? Thinking about it, for programmers who have experience in using dynamic proxies, it's easy to think that it must be based on the dynamic proxy technology behind it. Here's a look at the source code.
Registration of the Mapper interface
From the code above, we know that the implementation class of the BlogMapper interface is derived from session.getMapper, which is presumably based on dynamic proxy technology. Since we can get the BlogMapper interface from SqlSession, we definitely need to put it in somewhere before SqlSession can generate the proxy class we want. The code above has this line:
Followed by the code implementation of the addMapper method:
We see here that the mapper is actually added to mapperRegissry. Continue to follow the code:
See here we know that the above implementation of configuration.addMapper(BlogMapper.class); actually ends up in a HashMap named knownMappers, which is a private property of the MapperRegistry class, and is a property of the MapperRegistry class. knowMappers is a private property of the MapperRegistry class, which is a HashMap. Its Key is the current Class object and its value is a MapperProxyFactory instance.
To summarize: Mapper interfaces such as BlogMapper are added to a HashMap in the MapperRegistry. The MapperProxyFacory is a factory for creating Mapper Proxies, as the name suggests. Let's move on to the next section.
Generation of a Dynamic Proxy Class for the Mapper Interface
Above, we know that the Mapper interface is registered with the MapperRegistry - in a HashMap property named knowMappers. HashMap property named knowMappers, we call the methods of the Mapper interface like this:
Here, we trace the code implementation of the session.getMapper() method, where SqlSession is an interface with two implementation classes, one is DefaultSqlSession, and the other is SqlSessionManager. SqlSessionManager, here we use DefaultSqlSession. Why DefaultSqlSession? Why DefaultSqlSession? Because the build() method of the SqlSessionFactoryBuilder that we called when we initialized the SqlSessionFactory configured DefaultSqlSession, so let's go to the DefaultSession class and see what it says about session. getMapper(), getMapper(), getMapper(), getMapper(), getMapper(), getMapper(), getMapper(), getMapper(), and so on. getMapper (BlogMapper.class) is how to achieve:
As shown in the code, here getMapper call configuration.getMapper , this step in the operation is in fact ultimately call the MapperRegistry, and before we already know that the MapperRegistry is the storage for the session. MapperRegistry is stored in a HashMap, we continue to track in to see, then here get, certainly from this hashMap to get data. Let's take a look at the code:
We call the session.getMapper (BlogMapper.class); will eventually reach the above method, this method, according to BlogMapper's class object, with it as the key in the knowMappers find the corresponding value -- MapperProxyFactory(BlogMapper) object, and then call the newInstance() method of this object. Based on the name, we can guess that this method creates an object, the code is like this:
See here, it is clear that the final is through the Proxy.newProxyInstance generated a BlogMapper proxy object.Mybatis in order to complete the implementation of the Mapper interface, the use of the proxy pattern. Specifically the use of JDK dynamic proxy, this Proxy.newProxyInstance method to generate the proxy class of the three elements are:
Proxy pattern, the proxy class (MapperProxy) in the real completion of the logic of the method call. Let's post the MapperProxy code as follows:
We call Blog blog = mapper.selectBlog(1); which actually ends up calling the invoke method of this MapperProxy. In this code, if statement to determine, we want to call the method from the Object class, here means, if we call toString () method, then there is no need to do proxy enhancement, directly also call the original method.invoke () on the line. Only when you call a method like selectBlog(), you execute the enhanced call - that is, mapperMethod.execute(sqlSession, args); this line of code logic.
And mapperMethod.execute(sqlSession, args); this sentence will eventually perform the add, delete, change, and check, the code is as follows:
Then the next level down, it is the implementation of the JDBC that set of things, to get the link, execute it, get the ResultSet, and parse the ResultSet mapping into a JavaBean.
So far, we have figured out Blog blog = mapper.selectBlog(1); in the BlogMapper interface call to get the database data process, Mybaitis is how to generate an implementation class for the interface, and where to set off the final CRUD call. In fact, if we print out the mapper object from the slqSession before calling Blog blog = mapper.selectBlog(1); we see that the output looks like this:
Dynamic proxying is right, Java dynamic proxying is wonderful.
Above we mapped out how the Mapper interface finds its implementation class in a layer-by-layer fashion. We analyzed how the Mapper interface is registered, how the Mapper interface generates dynamic proxy objects, and how the Maper interface methods are ultimately executed. To summarize, these are the main points: