第六篇文章我們拿到了Mapper的一個代理對象,我們知道代理對象的執行其實是交給了InvocationHandler來處理的,也就是我們的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);
}
//我們根據當前的方法在緩存中獲取MapperMethod
final MapperMethod mapperMethod = cachedMapperMethod(method);
//執行相應的方法
return mapperMethod.execute(sqlSession, args);
}
1.獲取MapperMethod
private MapperMethod cachedMapperMethod(Method method) {
//在緩存中獲取
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
//如果沒有生成mapperMethod
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
//加入當前緩存
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
//初始化SqlCommand對象
this.command = new SqlCommand(config, mapperInterface, method);
//初始化MethodSignature對象
this.method = new MethodSignature(config, mapperInterface, method);
}
1.1初始化SqlCommand對象
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
//獲取當前方法名稱
final String methodName = method.getName();
//獲取當前方法 所屬的類
final Class<?> declaringClass = method.getDeclaringClass();
//這裏獲取MappedStatement 也就是我們解析mapper時生成的
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 {
//這裏獲取MappedStatement 的ID
name = ms.getId();
//當前SQL的類型(增刪改查)
type = ms.getSqlCommandType();
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
1.1.1獲取MappedStatement
private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
Class<?> declaringClass, Configuration configuration) {
//組裝ID 其實就是 之前設定的namespace.定義的ID(方法名稱)
String statementId = mapperInterface.getName() + "." + methodName;
//根據ID在緩存中獲取到了 直接返回
if (configuration.hasStatement(statementId)) {
return configuration.getMappedStatement(statementId);
} else if (mapperInterface.equals(declaringClass)) {
return null;
}
//如果當前方法不在當前接口中 往父類接口找
for (Class<?> superInterface : mapperInterface.getInterfaces()) {
if (declaringClass.isAssignableFrom(superInterface)) {
MappedStatement ms = resolveMappedStatement(superInterface, methodName,
declaringClass, configuration);
if (ms != null) {
return ms;
}
}
}
return null;
}
}
1.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();
}
//是不是沒有返回值 void類型
this.returnsVoid = void.class.equals(this.returnType);
//返回的類型 是不是集合或者數組
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
//返回的map類型
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
2.執行相應的方法
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//判斷當前sql的類型(增刪改查)
switch (command.getType()) {
case INSERT: {
//解析入參
Object param = method.convertArgsToSqlCommandParam(args);
//調用sqlSession的insert方法
//返回執行的行數
result = rowCountResult(sqlSession.insert(command.getName(), param));
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);
} else if (method.returnsMap()) {
//返回的是map
result = executeForMap(sqlSession, args);
} 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;
}
這裏可以最終調用的是sqlsession的方法,下一篇我們將詳細介紹每一個方法。