一、引言
手动使用Mybatis的四个步骤:
获取SqlSessionFactory对象
获取sqlSession对象
获取接口的代理对象(MapperProxy)
执行增删改查方法
MyBatis工作原理源码分析(一)——SqlSessionFactory的初始化 MyBatis工作原理源码分析(二)——获取SqlSession对象 前两篇详细分析了第一步和第二步,下面在此基础上,继续来分析接口的代理对象(MapperProxy)的获取。
二、源码分析再次说明:我们知道,在第二步中,获得了SqlSession(默认实现是DefaultSqlSession)。该SqlSession中包括执行具体Sql的Executor和保存全局配置信息的Configuration。
// 3、获取接口的实现类对象
//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法,传入接口名
DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class);
Department dept = mapper.getDeptById(1);
1、调用SqlSession的getMapper()方法
//调用的是Configuration的getMapper()方法,参数type为传入的接口全类名
//什么都不做,直接去configuration中找
@Override
public T getMapper(Class type) {
return configuration.getMapper(type, this);
}
2、SqlSession把包袱甩给了Configuration,接下来就看看Configuration
//在Configuration中,又调用了MapperRegistry的getMapper()方法
public T getMapper(Class type, SqlSession sqlSession) {
//烫手的山芋,俺不要,你找mapperRegistry去要
return mapperRegistry.getMapper(type, sqlSession);
}
3、Configuration也不要这烫手的山芋,接着甩给了MapperRegistry, 那咱看看MapperRegistry。
//MapperRegistry中的getMapper()方法
public T getMapper(Class type, SqlSession sqlSession) {
//能偷懒的就偷懒,俺把粗活交给MapperProxyFactory去做
final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//关键在这儿,将sqlSession传入,创建一个MapperProxy
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
//MapperProxyFactory中的newInstance()方法,传入SqlSession
public T newInstance(SqlSession sqlSession) {
final MapperProxy mapperProxy = new MapperProxy(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy mapperProxy) {
//动态代理我们写的dao接口
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
MapperRegistry中的knownMappers保存了每一个mapper对应的MapperProxyFactory,如下图。在MapperRegistry中的getMapper()方法中, 所以可以通过全类名从knownMappers中获取得到接口的MapperProxyFactory, 然后用这个MapperProxyFactory创建了接口的代理对象。
在Mybatis中,通过MapperProxy动态代理接口,也就是说,当我们执行自己写的Dao里面的方法的时候,其实是对应的MapperProxy在代理。那么,咱们就看看怎么获取MapperProxy对象:
获取接口的代理对象(MapperProxy)的时序图