热门推荐
聊聊Mybatis的binding模块
2024-12-04 17:11

聊聊Mybatis的binding模块

public <T> void addMapper(Class<T> type) {    if (type.isInterface()) {      if (hasMapper(type)) {        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }      boolean loadCompleted = false;      try {
        knownMappers.put(type, new MapperProxyFactory<>(type));        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }
@SuppressWarnings("unchecked")  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 {      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
先从knownMappers集合中找到对应的MapperProxyFactory实例

然后调用newInstance()方法
映射代理工厂类MapperProxyFactory

MapperProxyFactory的newInstance()方法:
public T newInstance(SqlSession sqlSession) {    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);    return newInstance(mapperProxy);
  }  @SuppressWarnings("unchecked")  protected T newInstance(MapperProxy<T> mapperProxy) {    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }
@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 {        return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
      }
    } catch (Throwable t) {      throw ExceptionUtil.unwrapThrowable(t);
    }
  }
private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {    try {      return MapUtil.computeIfAbsent(methodCache, method, m -> {        if (m.isDefault()) {          try {            if (privateLookupInMethod == null) {              return new DefaultMethodInvoker(getMethodHandleJava8(method));
            } else {              return new DefaultMethodInvoker(getMethodHandleJava9(method));
            }
          } catch (IllegalAccessException | InstantiationException | InvocationTargetException
              | NoSuchMethodException e) {            throw new RuntimeException(e);
          }
        } else {          return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
        }
      });
    } catch (RuntimeException re) {
      Throwable cause = re.getCause();      throw cause == null ? re : cause;
    }
  }
从methodCache中获取对应的MapperMethodInvoker

如果缓存没有,如果是方法是default方法就创建DefaultMethodInvoker对象,否则创建PlainMethodInvoker对象
默认方法调用类DefaultMethodInvoker

对于DefaultMethodInvoker类通过MethodHandle完成调用
private static class DefaultMethodInvoker implements MapperMethodInvoker {    private final MethodHandle methodHandle;    public DefaultMethodInvoker(MethodHandle methodHandle) {      super();      this.methodHandle = methodHandle;
    }    @Override
    public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {      return methodHandle.bindTo(proxy).invokeWithArguments(args);
    }
  }
private static class PlainMethodInvoker implements MapperMethodInvoker {    private final MapperMethod mapperMethod;    public PlainMethodInvoker(MapperMethod mapperMethod) {      super();      this.mapperMethod = mapperMethod;
    }    @Override
    public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {      return mapperMethod.execute(sqlSession, args);
    }
  }
    以上就是本篇文章【聊聊Mybatis的binding模块】的全部内容了,欢迎阅览 ! 文章地址:http://fabua.ksxb.net/quote/3330.html 
     动态      相关文章      文章      同类文章      热门文章      栏目首页      网站地图      返回首页 海之东岸资讯移动站 http://fabua.ksxb.net/mobile/ , 查看更多