首先,我们还是回顾一下上篇文件的类容。先看下这个测试类,大家还有印象吗:
- public class MybatisTest {
- @Test
- public void testSelect() throws IOException {
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- SqlSession session = sqlSessionFactory.openSession();
- try {
- FruitMapper mapper = session.getMapper(FruitMapper.class);
- Fruit fruit = mapper.findById(1L);
- System.out.println(fruit);
- } finally {
- session.close();
- }
- }
- }
上篇源码分析讲了 mybatis 一级缓存的实现原理。这次,我们来了解下 mybatis 接口的创建。
mapper接口的创建流程
SqlSession的getMapper()
首先,我们来看下 FruitMapper mapper = session.getMapper(FruitMapper.class); 这段代码,意思很简单,根据传入的class 获取这个对象的实例。这个流程有点复杂,阿粉带着大家来跟下源码:
首先还是ctrl + 左键点击 getMapper 方法,然后会进入到 SqlSession 的 getMapper() 方法。然后之前阿粉也带着大家了解了, SqlSession 的默认实现类是 DefaultSqlSession ,所以我们直接看下 getMapper() 在 DefaultSqlSession 里面的实现:
- @Override
- public <T> T getMapper(Class<T> type) {
- return configuration.getMapper(type, this);
- }
Configuration 的getMapper()
这里从 configuration 里面去获取, configuration 是全局配置对象,也就是上下文。参数 this 是当前的SqlSession 对象,继续跟进去看下:
- public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
- return mapperRegistry.getMapper(type, sqlSession);
- }
MapperRegistry 的getMapper()
mapperRegistry 对象是干什么的呢?继续点进去:
- 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);
- }
- }