因Mapper是interface,不能实例化对象,所以必须使用动态代理(使用JDK动态代理)创建代理对象MapperProxy,又因Mapper是接口,没有具体的方法体,所以MapperProxy的invoke方法中自行编写方法逻辑,下面介绍CURD的执行过程。
public class MapperProxy<T> implements InvocationHandler, Serializable {
略
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);} else {return cachedInvoker(method).invoke(proxy, method, args, sqlSession);}} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}}private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {try {return MapUtil.computeIfAbsent(methodCache, method, m -> {if (m.isDefault()) {try {if (privateLookupInMethod == null) {return new DefaultMethodInvoker(getMethodHandleJava8(method));} else {return new DefaultMethodInvoker(getMethodHandleJava9(method));}} catch (IllegalAccessException | InstantiationException | InvocationTargetException| NoSuchMethodException e) {throw new RuntimeException(e);}} else {return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));}});} catch (RuntimeException re) {Throwable cause = re.getCause();throw cause == null ? re : cause;}}
}###调用MapperBean中的非default方法private static class PlainMethodInvoker implements MapperMethodInvoker {private final MapperMethod mapperMethod;public PlainMethodInvoker(MapperMethod mapperMethod) {super();this.mapperMethod = mapperMethod;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {return mapperMethod.execute(sqlSession, args);}}
可见mapperMethod来执行execute,携带sqlSession和参数(默认的statement是prepareStatement)
mapperMethod类中有2个属性,分别是SqlCommand、MethodSignature,均是MapperMethod的内部类。
public class MapperMethod {private final SqlCommand command;private final MethodSignature method;public static class SqlCommand {类全路径名+方法名:com.orion.mapper.TAccountMapper.selectByPrimaryKeyprivate final String name;枚举,CURD那几种,如SELECTprivate final SqlCommandType type;}public static class MethodSignature {private final boolean returnsMany;private final boolean returnsMap;private final boolean returnsVoid;private final boolean returnsCursor;private final boolean returnsOptional;返回类型private final Class<?> returnType;private final String mapKey;private final Integer resultHandlerIndex;private final Integer rowBoundsIndex;参数private final ParamNameResolver paramNameResolver;}
}
SELECT
debug下去最终执行execute之类的方法,而执行的execute方法是sqlSession,注意sqlSession是携带configuration的,configuration里面有mappedStatement(所有方法集合),最后根据SqlCommand中的name作为id从mappedStatement中获取相应的MappedStatement对象。
DefaultSqlSession:private <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {try {MappedStatement ms = configuration.getMappedStatement(statement);return executor.query(ms, wrapCollection(parameter), rowBounds, handler);} catch (Exception e) {throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);} finally {ErrorContext.instance().reset();}}