@Override public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this); }
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); }
MapperProxyFactory类型,然后调用mapperProxyFactory.newInstance(sqlSession)方法,创建mapper的实例。
public class MapperRegistry { private final Configuration config; /** * 已知的Mapper集合,有添加mapper的方法,通过添加方法,将所有的Mapper接口添加到已知集合里 * key:Mapper接口的class对象 * value:MapperProxyFactory,从名字上看是一个mapper代理工厂 */ private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>(); public MapperRegistry(Configuration config) { this.config = config; } @SuppressWarnings("unchecked") public <T> T getMapper(Class<T> type, SqlSession sqlSession) { //根据Class类型从已知的mapper集合中查找 final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); //如果查找失败抛出异常 if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } try { //动态代理创建一个mapper的实例 return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } } public <T> boolean hasMapper(Class<T> type) { return knownMappers.containsKey(type); } /** * 添加mapper * @param type * @param <T> */ public <T> void addMapper(Class<T> type) { //如果是个接口 if (type.isInterface()) { //如果已经存在 if (hasMapper(type)) { throw new BindingException("Type " + type + " is already known to the MapperRegistry."); } boolean loadCompleted = false; try { //将mapper放入knownMappers中 knownMappers.put(type, new MapperProxyFactory<T>(type)); // It's important that the type is added before the parser is run // otherwise the binding may automatically be attempted by the // mapper parser. If the type is already known, it won't try. MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } } /** * @since 3.2.2 */ public Collection<Class<?>> getMappers() { return Collections.unmodifiableCollection(knownMappers.keySet()); } /** * @since 3.2.2 */ public void addMappers(String packageName, Class<?> superType) { ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>(); resolverUtil.find(new ResolverUtil.IsA(superType), packageName); Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses(); for (Class<?> mapperClass : mapperSet) { addMapper(mapperClass); } } /** * 通过扫描包名向knownMappers添加mapper * @since 3.2.2 */ public void addMappers(String packageName) { addMappers(packageName, Object.class); } }
(4)MapperProxyFatory的newInstance方法
调用newInstance(sqlSession)方法时,会生成一个MapperProxy对象,从名字就能看出,这就是Mapper的代理类,然后再调用Proxy.newProxyInstance完成代理对象的实例化。
public class MapperProxyFactory<T> { private final Class<T> mapperInterface; private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>(); public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } public Class<T> getMapperInterface() { return mapperInterface; } public Map<Method, MapperMethod> getMethodCache() { return methodCache; } @SuppressWarnings("unchecked") protected T newInstance(MapperProxy<T> mapperProxy) { /** * 使用动态代理实例化代理对象 * 三个参数: * 1:指明生成代理对象使用哪个类加载器 * 2:指明生成哪个对象的代理对象,通过接口指定 * 3:代理对象,MapperProxy实现了InvocationHandler接口 */ return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { //创建一个 MapperProxy对象 final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); //使用动态代理实例化对象 return newInstance(mapperProxy); } }
(5)mapper的实际代理对象MapperProxy
可以看出MapperProxy实现了InvocationHandler接口,重写了invoke方法。
调用Mapper中的方法时,会调用invoke方法,invoke方法需要三个参数,proxy指的是代理对象,method指的是调用被代理对象中的方法,args是方法的参数。
在inoke方法中,通过方法获取方法所在类的class信息,如果是个接口,会将被调用的方法封装为一个MapperMethod对象,然后调用它的execute方法。
/** * mapper的代理类 */ public class MapperProxy<T> implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; private final SqlSession sqlSession; private final Class<T> mapperInterface; /** * 方法缓存集合,当调用接口中的方法时,会将封装一个MapperMethod对象做为value,方法作为key,放入集合中 */ private final Map<Method, MapperMethod> methodCache; public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; this.methodCache = methodCache; } /** * 通过动态代理调用被代理对象的方法时,实际走的是invoke方法,在invoke方法中通过method.invoke方式完成方法的调用 * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override 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); } //如果是接口,通过cachedMapperMethod方法完成MapperMethod的实例化 final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); } 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; } @UsesJava7 private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable { final Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class .getDeclaredConstructor(Class.class, int.class); if (!constructor.isAccessible()) { constructor.setAccessible(true); } final Class<?> declaringClass = method.getDeclaringClass(); return constructor .newInstance(declaringClass, MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC) .unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args); } /** * 默认的方法 */ private boolean isDefaultMethod(Method method) { return (method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC && method.getDeclaringClass().isInterface(); } }
(6)MapperMethod类
MapperMethod构造函数中会对SqlCommand对象和MethodSignature对象初始化。SqlCommand中封装了SQL命令类型以及方法的名称(XML中配置的id+Mapper所在接口路径),MethodSignature中封装了方法参数、返回类型等信息。
在SqlCommand初始化时,又根据接口和调用的方法信息创建了MappedStatement对象,封装了XML当中标签的信息。
执行MapperMethod的execute方法时先判断SQL命令类型(增删改查等),然后调用的是SqlSession中的方法执行SQL命令。
public class MapperMethod { /** * 封装了SQL命令类型(增删改查等) */ private final SqlCommand command; /** * 封装了方法参数、返回类型等信息 */ private final MethodSignature method; /** * 构造函数 * @param mapperInterface * @param method * @param config */ public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) { //初始化SqlCommand this.command = new SqlCommand(config, mapperInterface, method); //初始化MethodSignature this.method = new MethodSignature(config, mapperInterface, method); } public Object execute(SqlSession sqlSession, Object[] args) { Object result; //判断SQL标签类型 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()) {//返回类型是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; } ...... /** * 返回多条数据的查询方法 * @param sqlSession * @param args * @param <E> * @return */ private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { List<E> result; //处理参数 Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) {//如果是分页查询 RowBounds rowBounds = method.extractRowBounds(args); //调用sqlSession的方法执行查询 result = sqlSession.<E>selectList(command.getName(), param, rowBounds); } else { result = sqlSession.<E>selectList(command.getName(), param); } // issue #510 Collections & arrays support if (!method.getReturnType().isAssignableFrom(result.getClass())) { if (method.getReturnType().isArray()) { return convertToArray(result); } else { return convertToDeclaredCollection(sqlSession.getConfiguration(), result); } } return result; } ...... public static class SqlCommand { /** * XML标签中ID + Mapper所在类/接口的路径 */ private final String name; /** * SQL命令类型 * 包含了UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH; */ private final SqlCommandType type; /** * 构造函数 * @param configuration * @param mapperInterface * @param method */ public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) { final String methodName = method.getName();//方法名 final Class<?> declaringClass = method.getDeclaringClass();//方法所在类/接口的class对象 //创建MappedStatement对象,这个对象封装了XML当中标签的信息 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 { name = ms.getId(); type = ms.getSqlCommandType(); if (type == SqlCommandType.UNKNOWN) { throw new BindingException("Unknown execution method for: " + name); } } } public String getName() { return name; } public SqlCommandType getType() { return type; } private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName, Class<?> declaringClass, Configuration configuration) { //statementId,是方法名+类/接口的完整路径 eg:org.mybatis.example.BlogMapper.selectBlog String statementId = mapperInterface.getName() + "." + methodName; //如果Configuration中已经存在 if (configuration.hasStatement(statementId)) { //直接从初始化阶段生成的mappedStatements中,获取当前SQL语句的mappedStatement return configuration.getMappedStatement(statementId); } else if (mapperInterface.equals(declaringClass)) { /* * mapperInterface如果是接口应该是interface 包名.接口名,declaringClass是包名.接口名 * 还不清楚什么情况下mapperInterface和declaringClass相同,反正就是如果它们两个相同就返回null */ return null; } //如果初始化阶段还没有加载过,找到当前方法所在的接口,getInterfaces()获取这个对象实现的所有接口 for (Class<?> superInterface : mapperInterface.getInterfaces()) { if (declaringClass.isAssignableFrom(superInterface)) { //生成MappedStatement MappedStatement ms = resolveMappedStatement(superInterface, methodName, declaringClass, configuration); if (ms != null) { return ms; } } } return null; } } public static class MethodSignature { private final boolean returnsMany;//返回多条结果 private final boolean returnsMap;//返回Map private final boolean returnsVoid;//返回空 private final boolean returnsCursor;//返回游标 private final Class<?> returnType;//返回类型 private final String mapKey; private final Integer resultHandlerIndex;//resultHandler类型参数的位置 private final Integer rowBoundsIndex;//rowBound类型参数的位置 private final ParamNameResolver paramNameResolver;//参数处理类 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(); } this.returnsVoid = void.class.equals(this.returnType); this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray(); this.returnsCursor = Cursor.class.equals(this.returnType); 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); } ...... private Integer getUniqueParamIndex(Method method, Class<?> paramType) { Integer index = null; final Class<?>[] argTypes = method.getParameterTypes(); for (int i = 0; i < argTypes.length; i++) { if (paramType.isAssignableFrom(argTypes[i])) { if (index == null) { index = i; } else { throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters"); } } } return index; } private String getMapKey(Method method) { String mapKey = null; if (Map.class.isAssignableFrom(method.getReturnType())) { final MapKey mapKeyAnnotation = method.getAnnotation(MapKey.class); if (mapKeyAnnotation != null) { mapKey = mapKeyAnnotation.value(); } } return mapKey; } } }
参考:
MyBatis 源码分析——动态代理
mybatis源码分析5 - mapper读写数据库完全解析