编程知识 cdmana.com

【Mybatis】- mapper.java and mapper.xml How to map it - source code analysis

In the last blog we talked about sqlSession How did it come about . In this blog we talk about mapper.java and mapper.xml How it's mapped .

In the program, we only have mapper.java Interface , No, mapper Implementation class , So how to call a method ?

mybatis In all mapper Interface implementation classes can be seen as mapperProxy,mapper proxy class , And then call MapperProxy.invoke() Method ,invoke() Method will execute the corresponding sql sentence , And return the result .

public class MapperProxy<T> implements InvocationHandler, Serializable {

  private static final long serialVersionUID = -6424540398559729838L;
  private final SqlSession sqlSession;
  private final Class<T> mapperInterface;
  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;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    // Start execution sql sentence 
    return mapperMethod.execute(sqlSession, args);
  }
}

So how to call mapperProxy What about the proxy class ? Let's take a look at the decomposition :

1、 The program is in sqlSession Will call configuration Of getMapper Method

 @Override
  public <T> T getMapper(Class<T> type) {
    return getConfiguration().getMapper(type, this);
  }

2、 Used at that time configuration Of getMapper When the method is used , Would call mapperRegistry Of getMapper Method

 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

3、 When using mapperRegistry Of getMapper When the method is used , Would call mapperProxyFactory.newInstance(sqlSession) Method , Get one MapperProxy object

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      //  Transferred to the mapperProxyFactory
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

 

4、 ad locum , Through the first T newInstance(SqlSession sqlSession) Method will get a MapperProxy object , And then call T newInstance(MapperProxy<T> mapperProxy) Generate the proxy object and return .

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    // Method calls for all dynamic proxy classes , All will be handed over to InvocationHandler Interface implementation class invoke() How to deal with . This is the key to dynamic proxy .
    // Dynamic proxy we wrote dao Interface , The first parameter is the class loader , The second parameter is mapper Interface , The third parameter is mapper proxy class 
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {

    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);

}
  

5、 And look at MapperProxy Code for , You can see the following :

public class MapperProxy<T> implements InvocationHandler, Serializable {

  //mapper Dynamic agent implementation InvocationHandler Interface , rewrite invoke Method 
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        // Here said InvocationHandler Of invoke Method , Dynamic proxies end up calling InvocationHandler Of invoke Method 
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    //sqlSession We went to the last blog to get , Now I have got it mapper Proxy class for interface , So here's where we start sql
    return mapperMethod.execute(sqlSession, args);
  }
}

The MapperProxy Class implements the InvocationHandler Interface , And implemented the invoke Method .

In this way , We just need to write Mapper.java Interface class , When really executing a Mapper At the interface , It will be forwarded to MapperProxy.invoke Method , This method calls the following sqlSession.cud>executor.execute>prepareStatement Wait for a series of methods , complete SQL Execution and return of .

Through the above mapperProxy proxy class , We can use it easily mapper.java and mapper.xml 了 .

版权声明
本文为[Wooden pine cat]所创,转载请带上原文链接,感谢

Scroll to Top