为什么mybatis可以通过一个接口实现对数据库的操作

1、mybatis使用实例

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
}

这是从mybatis官网
截取出来的代码,
BlogMapper 是一个接口

2原理解析
mybatis是通过动态代理技术生成了一个proxy类,
首先是这个类DefaultSqlSession类然后挨个点进去看最后

  public  T getMapper(Class type) {
    return configuration.getMapper(type, this);
  }
 protected T newInstance(MapperProxy mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

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

到这里就可以发现通过传入一个类,可以获取一个mapperInterface 类的代理类。
(T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy)
mapperInterface 是刚刚传入的参数。
所以通过动态代理生成的类调用方法,最后实现都是在mapperProxy的invoke类里面

3、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 if (method.isDefault()) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

所有的方法最后都会通过**mapperMethod.execute(sqlSession, args)**调用
结论:mybatis定义接口,并生成接口的动态代理类,代理类的每次方法调用都会经过MapperProxy中的invoke方法
mapperMethod中含有参数类名BlogMapper全路径、方法名selectBlog、参数可以找到相对应的mapper.xml中的sql,再通过jdbc就能实现对数据库的操作了。

你可能感兴趣的:(mybatis)