为啥Mybatis的接口不需要实现类

对啊,为什么不需要啊?
猜猜,可能是动态代理生成了接口的对应的类
在这里插入图片描述
果然是动态生成的

那是啥时候生成的呢

那就是我通过class获取Mapper时生成的

   UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

通过上面我们一层层进入到下面的代码

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);// 1
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession); // 2
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  1. 获取对应类型的MapperProxyFactory
  2. 创建MapperProxy,也就是我们的UserMapper,我们就可以在其上调用我们在接口中定义的方法了

具体是怎么生成代理的呢?

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy); // 1
  }
  1. 进入newInstance方法如下
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

在这里我们又到了Proxy.newProxyInstance代码,就是JDK创建代理的方法。

稍等,生成Proxy的MapperProxyFactory从而来

别着急我还没有说完呢
knownMappers.get(type) 刚才我们通过这个获取的MapperProxyFactory<T>,其中包含生成代理的接口集合mapperInterface
现在我说说,MapperProxyFactory从何而来,简单说就是在解析XML时创建的
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
我们一直进入到parseConfiguration方法,其中mapperElement(root.evalNode("mappers"));方法就是解析Mapper文件,注册的MapperProxyFactoryMapperRegistry。一直跟踪到下面的方法,在MapperRegistry中。

 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)); // 1
      MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
      parser.parse();
      loadCompleted = true;
    } finally {
      if (!loadCompleted) {
        knownMappers.remove(type);
      }
    }
  }
  1. 一直追踪到knownMappers.put(type, new MapperProxyFactory<>(type));方法我们找到了,在创建代理的时候,是用的是get方法,MapperProxyFactory就是从这添加的。

总结

今天我们从为Mapper接口创建代理对象开发,说到具体怎么创建对象。

从初始化配置文件,创建MapperProxyFactory<T>,到当获取Mapper,根据类型或者对应的MapperProxyFactory,使用JDK动态代理API创建代理对象。于是我们就可以调用法了。

演示相关代码

欢迎讨论学习

使用JDK API实现动态代理和源码分析

Mybatis 插件和动态代理

面试官问,为啥Mybatis的接口不需要实现类

面试官问,Mybatis插件增强逻辑的顺序怎么控制


子龙哦
60 声望0 粉丝