Mybatis获取Mapper的过程
概览
- mybatis加载mapper的代码
- 具体实例化Mapper的过程
- 总结
mybatis加载mapper的代码
//前置加载配置文件省略
//实际上获取的是DefaultSqlSessionFactory 具体为何可以看对应的build方法
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//得到DefaultSqlSession
SqlSession session = sqlSessionFactory.openSession();
//通过DefaultSqlSession获取mapper
UserMapper mapper = session.getMapper(UserMapper.class);
具体实例化Mapper的过程
因为UserMapper mapper = session.getMapper(UserMapper.class)在创建SqlSession的时候实际上创建的是DefaultSqlSession,所以我们直接进入到DefaultSqlSession的对应getMapper方法中:
//org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper(Class<T> type)
@Override
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
从代码中我们能够看到,实际上获取的是 org.apache.ibatis.session.Configuration#getMapper(Class<T> type, SqlSession sqlSession)这个方法,那么现在我们进到对应的方法中看一下:
//org.apache.ibatis.session.Configuration#getMapper(Class<T> type, SqlSession sqlSession)
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
能够清楚的看到,这个方法实际上调用的是 org.apache.ibatis.binding.MapperRegistry#getMapper(Class<T> type, SqlSession sqlSession)这个方法,继续查看对应的方法内容
//org.apache.ibatis.binding.MapperRegistry#getMapper(Class<T> type, SqlSession sqlSession)
@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);
}
}
我们能够看到,重点的代码实现是在mapperProxyFactory.newInstance(sqlSession);所以我们现在进入org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)这个方法中:
//org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
通过newInstance(mapperProxy),找到了类中的另一个方法org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>),代码如下:
//org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>)
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
//代理生成的过程
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
具体org.apache.ibatis.binding.MapperProxy类的内容,这一次先不看,下一次在查看具体调用流程的时候再讲。
总结
通过源码的调用过程,我们知道在mybatis中获取对应的Mapper的时候,其实获取的是一个代理(代理不太懂的,可以网上找相关的博文,挺多的,这一点儿就不仔细说了),但是在拿到这个代理之后,mybatis到底做了什么事情,下一篇继续,至于mybatis的SqlSessionFactory的初始化过程,咱们再等等,放到后面再说。