UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectByPrimaryKey(1);
这篇文章我们将从上面两行代码看起,首先就是获得mapper文件对应的映射类,然后执行里面的数据库操作:
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
在方法里面将映射类的class对象和当前session作为参数在configuration里面查找:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
然后从存放mapper的工厂里面来查找:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//根据class对象获取它对应的代理工厂
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);
}
}
由代理工厂为我们生成一个对应接口的代理对象:
public T newInstance(SqlSession sqlSession) {
//封装成一个代理类
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
//作为参数实例化
return newInstance(mapperProxy);
}
将当前的会话、接口、和方法的缓存封装成一个mapper代理类,然后实例化:
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
实际上刚刚创建的MapperProxy就是一个拦截器,那么我们所关注的点就是它里面的invoke方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//当前代理类是否是执行方法的声明类,如果是,直接执行
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
//如果是默认的方法,则按照执行默认方法的逻辑处理
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
首先会判断声明当前方法的是否是一个类,如果不是就需要创建一个MapperMethod :
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {