在 mybatis源码学习之执行过程分析(1)——SqlSessionFactory及SqlSession的创建中,跟踪到openSession()
方法返回了DefaultSqlSession,并持有Configuration的引用(Configuration的实例化见mybatis源码学习——Configuration类及其初始化过程、TypeHandler、TypeAlias)。
当我们通过session.getMapper(UserMapper.class)
获取Mapper接口时,其实调用了Configuration中的getMapper()
方法。
回过头来看我们的代码:
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
DefaultSqlSession.java
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
可以看到是调用了Configuration中的getMapper()方法。在这里是因为Mapper信息保存在MapperRegistry中的final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap()
中(详细过程见Configuration的实例化和xml的解析的分析)。
Configuration.java
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
MapperRegistry.java
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//在这里拿到了Mapper接口所在代理工厂
MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if(mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
可以看到就是对HashMap的get()操作,并转换为MapperProxyFactory。
至此我们就拿到了UserMapper接口。因为它被MapperProxyFactory中的mapperInterface所引用,获取过程如下图:
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();
...
}
总结
至此mapper接口的获取就结束了,可以看到实质上拿到的是一个MapperProxy代理类。
下面继续分析接口中方法的调用(即代理的调用)。