开发工具
eclipse
代理对象
MyBatis最终会为代码逻辑中的接口创建代理对象,由代理对象执行方法
断点代码1:
//接口的代理对象执行getEmpByIdAndLastName(Integer i,String str)
Employee employee = mappper.getEmpByIdAndLastName(1,"tom");
断点查看
- 第一步:
来到MapperProxy类下
public class MapperProxy<T> implements InvocationHandler, Serializable {...}
InvocationHandler接口负责动态代理
InvocationHandler
重写InvocationHandler下invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//如果是在Object里声明的方法直接放行
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);
}
//如果是代理对象的接口下的方法,判断内代码没走的话调用
//把Method包装成MapperMethod
//参数args是Array类型,包含了不止一个参数,可以是多个字段的值
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
断点代码2:
return mapperMethod.execute(sqlSession, args);
断点查看
- 第一步:
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//DeBug默认选中
//执行前先判断一下,不同的业务走不同的case语句。
switch (command.getType()) {
case INSERT: {
//先把接口方法里的参数转换成sql能识别的参数。
Object param = method.convertArgsToSqlCommandParam(args);
//result是返回值
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:
//method.returnVoid()没有返回值
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result