mybatis的Demo中的代码段为:
1 SubjectDao subjectDao=sqlSession.getMapper(SubjectDao.class);
对应的源码为:
1 @Override 2 public <T> T getMapper(Class<T> type) { 3 return configuration.<T>getMapper(type, this); 4 }
1 public <T> T getMapper(Class<T> type, SqlSession sqlSession) { 2 return mapperRegistry.getMapper(type, sqlSession); 3 }
1 @SuppressWarnings("unchecked") 2 public <T> T getMapper(Class<T> type, SqlSession sqlSession) { 3 //创建mapper代理工厂 type的值为UserDao接口类实例 4 final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); 5 if (mapperProxyFactory == null) { 6 throw new BindingException("Type " + type + " is not known to the MapperRegistry."); 7 } 8 try { 9 //返回Mapper的代理实例 10 return mapperProxyFactory.newInstance(sqlSession); 11 } catch (Exception e) { 12 throw new BindingException("Error getting mapper instance. Cause: " + e, e); 13 } 14 }
1 public T newInstance(SqlSession sqlSession) { 2 final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); 3 //返回的MapperProxy实例 4 return newInstance(mapperProxy); 5 }
myBatis指明具体调用的接口
1 List<Subject> subjectList=subjectDao.selectSubject01();
其源码分析为因为之前返回的时mapper的类实例,调用具体方法会使用invoke方法即:
1 @Override 2 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 3 try { 4 //判断这个类是否是方法类的class对象 5 if (Object.class.equals(method.getDeclaringClass())) { 6 return method.invoke(this, args); 7 } else if (isDefaultMethod(method)) { 8 //调用默认方法 9 return invokeDefaultMethod(proxy, method, args); 10 } 11 } catch (Throwable t) { 12 throw ExceptionUtil.unwrapThrowable(t); 13 }
//将方法加入到此方法 14 final MapperMethod mapperMethod = cachedMapperMethod(method);
//调用执行器 15 return mapperMethod.execute(sqlSession, args); 16 }
此执行器会判断此接口是执行哪一种类型的sql,
1 public Object execute(SqlSession sqlSession, Object[] args) { 2 Object result; 3 switch (command.getType()) { 4 case INSERT: { 5 Object param = method.convertArgsToSqlCommandParam(args); 6 result = rowCountResult(sqlSession.insert(command.getName(), param)); 7 break; 8 } 9 case UPDATE: { 10 Object param = method.convertArgsToSqlCommandParam(args); 11 result = rowCountResult(sqlSession.update(command.getName(), param)); 12 break; 13 } 14 case DELETE: { 15 Object param = method.convertArgsToSqlCommandParam(args); 16 result = rowCountResult(sqlSession.delete(command.getName(), param)); 17 break; 18 } 19 case SELECT: 20 if (method.returnsVoid() && method.hasResultHandler()) { 21 executeWithResultHandler(sqlSession, args); 22 result = null; 23 } else if (method.returnsMany()) { 24 result = executeForMany(sqlSession, args); 25 } else if (method.returnsMap()) { 26 result = executeForMap(sqlSession, args); 27 } else if (method.returnsCursor()) { 28 result = executeForCursor(sqlSession, args); 29 } else { 30 Object param = method.convertArgsToSqlCommandParam(args); 31 result = sqlSession.selectOne(command.getName(), param); 32 } 33 break; 34 case FLUSH: 35 result = sqlSession.flushStatements(); 36 break; 37 default: 38 throw new BindingException("Unknown execution method for: " + command.getName()); 39 } 40 if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { 41 throw new BindingException("Mapper method '" + command.getName() 42 + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); 43 } 44 return result; 45 }