乐趣区

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

为啥 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 插件加强逻辑的程序怎么管制

退出移动版