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.