总结
调用的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;
}
}
}