總結
調用的getMapper
方法(1)調用Configuration
的getMapper
方法(2)調用MapperRegistry
的getMapper
方法(3)調用MapperProxyFactory
的newInstance
方法(4)調用兄弟newInstance
方法(6)使用動態代理模式去設置mapperProxy
爲目標Dao方法的代理(7),MapperProxy這個類中的invoke實現是利用MapperMethod的execute
來執行的(19)
源碼片段
已省略部分細節,只保留了主要方法調用。上文的括號中數字對應源碼行數。
sqlSession.getMapper(){//去DefaultSqlSession
return configuraion.<T>getMapper(type,this) {//去Configuration.java
return mapperRegistry.getMapper(type, sqlSession) {//去MapperRegistry.java
return mapperProxyFactory.newInstance(sqlSession){//去MapperProxyFactory.java
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProy) {//兄弟方法
return (T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),new Class[]{mapperInterface},mapperProxy/*加強Dao接口的代理類MapperProxy的對象*/))
}
}
}
}
}
class MapperProxy<T> implements InvocationHandler, Serializable{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
...
final MapperMethod mapperMethod = cacheMapperMethod(method);
return mapperMethod.execute(sqlSession, args){//去MapperMethod.java
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
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()) {
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;
}
}
}