This is the 23rd day of my participation in the August More Text Challenge.More challenges in August
Sequence diagram
sequenceDiagram
participant S as Client
participant A as DefaultSqlSession
participant B as Configuration
participant C as MapperRegistry
participant D as MapperProxyFactory
participant E as MapperProxy
S ->> A : getMapper
A ->> B : getMapper
B ->> C : getMapper
C ->> D : newInstance
D ->> E : new
E -->> D : MapperProxy
D -->> S : ProxyInstance
The detailed steps
Client
// Get the proxy object of the Mapper interface
PurchaseMapper mapper = sqlSession.getMapper(PurchaseMapper.class);
Copy the code
DefaultSqlSession#getMapper
@Override
public <T> T getMapper(Class<T> type) {
/** * 1. The configuration object is created by parsing the configuration file when creating DefaultSqlSessionFactory. 2
return configuration.getMapper(type, this);
}
Copy the code
Configuration#getMapper
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
/** * Obtain the Mapper object from the Mapper type and sqlSession.@linkConfiguration#addMapper(java.lang.class)} Saves the MapperProxyFactory object
return mapperRegistry.getMapper(type, sqlSession);
}
Copy the code
MapperRegistry#getMapper
The addMapper method is described in the mappers tag parsing article Mybatis source
/** * finds the specified mapping file and generates a proxy implementation * for the mapping interface based on the mapping file information@paramType Mapping interface *@param sqlSession sqlSession
* @param<T> Map interface type *@returnThe proxy implementation object */
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// Find the agent factory for the specified interface
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
// Create an instance of the corresponding proxy using mapperProxyFactory
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: "+ e, e); }}Copy the code
MapperProxyFactory#newInstance
// Generate a MapperProxy object
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
// Create a MapperProxy instance
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
// Create a proxy object for the mapperInterface interface
return newInstance(mapperProxy);
}
Copy the code
MapperProxy
/** * MapperProxy transfers method calls to MapperMethod object execute method based on dynamic proxy. * that is, as long as MapperProxy object is used as the mapping interface implementation, You can fully implement the function of accessing database operations for mapping interfaces * *@author Clinton Begin
* @author Eduardo Macarron
*/
public class MapperProxy<T> implements InvocationHandler.Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
// The methodCache property maintains the mapping between interface methods and MapperMethod objects
// The key of the Map is a method, and the value is a MapperMethod object. Using this attribute, the method in MapperProxy (that is, the mapping interface) is bound to MapperMethod
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; }}Copy the code
This is how Mybatis gets Mapper instances.