一、第一阶段 getMapper
1.通过sqlSession.getMapper(Class)
MemberDao mapper = sqlSession.getMapper(MemberDao.class);
2.DefaultSqlSession
调用sqlSession的实现DefaultSqlSession中的getMapper方法
@Override
public <T> T getMapper(Class<T> type) {//type dao.class
return configuration.<T>getMapper(type, this);
}
3.Configuration
通过configuration中的getMapper方法,将type和DefaultSqlSession传递过去
private final Configuration configuration;
return configuration.<T>getMapper(type, this);
//this ---> DefaultSqlSession
通过MapperRegistry 去调用里面的getMapper(Class type, SqlSession sqlSession)方法
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
4.MapperRegistry
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 根据指定的type,查找对应的MapperProxyFactory对象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
//如果没有配置mapper,则找不到对应的MapperProxyFactory , 抛出异常
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//mapperProxyFactory.newInstance(sqlSession); 生成相应的代理对象
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
5.MapperProxyFactory
创建MapperProxy对象 ,每次调用都对重新创建,使用动态代理,将mapperProxy返回出去
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
流程
SqlSession (getMapper) —> SqlSessionTemplate implements SqlSessio (getMapper) —> Configuration (getMapper) —> MapperRegistry (getMapper) ----> MapperProxyFactory (newInstance) —>(return) || Configuration ----> SqlSessionTemplate —> SqlSession
二、第二阶段 getMapper.xxx
1.MapperProxy
@Override
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);
}
//缓存mapperMapperMethod实例
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
1.1 cachedMapperMethod
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = methodCache.get(method);
//判断method 是否在缓存中,不存在的话就去创建一个mapperMethod
if (mapperMethod == null) {
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
1.2 MapperMethod
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) { this.command = new SqlCommand(config, mapperInterface, method);//负责获取dao中的名字id,使用的数据库,以及数据的操作方式,SELECR、INSERT。。。 this.method = new MethodSignature(config, mapperInterface, method);//负责判断返回值的类型 }
1 SqlCommand
- 负责获取dao中的名字id,使用的数据库,以及数据的操作方式,SELECR、INSERT。。。
public static class SqlCommand { private final String name; //dao的名字/方法名 private final SqlCommandType type; //操作的类型 例如UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH; public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) { final String methodName = method.getName(); // 获取要进行操作的方法名 //获取方法声明的接口类型 final Class<?> declaringClass = method.getDeclaringClass(); //获取xml中每个方法构建的MappedStatement MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass, configuration); if (ms == null) { if (method.getAnnotation(Flush.class) != null) { name = null; type = SqlCommandType.FLUSH; } else { throw new BindingException("Invalid bound statement (not found): " + mapperInterface.getName() + "." + methodName); } } else { name = ms.getId();//获取xml中的 id type = ms.getSqlCommandType();//获取操作的类型UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH; if (type == SqlCommandType.UNKNOWN) { throw new BindingException("Unknown execution method for: " + name); } } }
2 MethodSignature
- 负责判断返回值的类型
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) { //该方法的返回值类型 Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface); //返回值的对象时进入 if (resolvedReturnType instanceof Class<?>) { this.returnType = (Class<?>) resolvedReturnType; } else if (resolvedReturnType instanceof ParameterizedType) { this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType(); } else { this.returnType = method.getReturnType(); } //判断返回值是否为空 this.returnsVoid = void.class.equals(this.returnType); //是否返回多个数据 this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray(); //是否返回的是Cursor类型 this.returnsCursor = Cursor.class.equals(this.returnType); //获取到mapKey 即@MapKey值 this.mapKey = getMapKey(method); //是否返回map this.returnsMap = this.mapKey != null; //参数中是否有RowBounds 即mybatis的分页工具类 this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class); //是否有ResultHandler类 this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class); //获取到参数值 即@Param的值,如果有则为里面的value值 如果没有 则为'0','1','2'之类的 this.paramNameResolver = new ParamNameResolver(configuration, method); }
1.3 mapperMethod.execute()
public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { //执行判断方法command.getType()为要操作的操作类型UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH case INSERT: { Object param = method.convertArgsToSqlCommandParam(args); //参数转换 result = rowCountResult(sqlSession.insert(command.getName(), param)); //sql执行 break; } case UPDATE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } case DELETE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } case SELECT: //返回为空 if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; //返回多个 } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); //返回map } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); //返回Cursor } else if (method.returnsCursor()) { //返回单个对象 result = executeForCursor(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; //sql执行完成返回结果集 }