mybatis源码解析-----执行流程1
2017-06-17 16:51
671 查看
用了这么久mybatis,不了解一下执行过程怎么可以呢,是吧,今天我就带大家一起看看mybatis是怎么执行的。如果我们不集成spring的话是如何使用mybatis的?根据官网的教程我们一般都是使用以下方式吧:
这里获得了SqlSessionFactory,接下来就是打开一个session,也就是获得SqlSession,然后就获得一个Mapper实例(mybatis通过反射为我们生成的),然后就可以调用这个mapper接口里的方法了,如果是查询的话那么我们就可以通过对应的实例去接收,整个过程就几行代码,如果我们使用jdbc的话大家应该也知道那个代码量还是非常多的,还要自己new一个实例进行封装,现在这些事mybatis都帮我们做了,接下来我们就看看mybatis怎么帮我们做的。
通过上面的代码可以看到,入口就在build方法,这个方法内部通过XMLConfigBuilder对配置文件进行解析,解析部分就不分析了,主要对xml文件的解析,不懂xml文件解析的话可以先学习一下,我主要分析它如何获取mapper,以及如何封装参数返回给我们。
首先,如何获取mapper,毫无疑问入口就在getMapper方法,跟进去就发现是通过Configuration这个类来获取的,我们上一篇讨论了一些相关的基础类,它里面有一个MapperRegistry类,先在来看看核心是如何实现的,首先这个类里面有一个knownMappers成员变量,保存的是已知的mapper,那什么是已知的mapper?这个就是在刚才解析配置文件的时候生成的,解析配置文件的时候会解析相应的mapper文件,mapper配置里面不是要指定namespace吗?mybatis通过这个namespace生成一个Class对象作为键,值就是MapperProxyFactory<?>,addMapper方法里面有一句:
好了,继续看,mybatis帮我们生成了一个MapperProxy类的实例,可以看到这个实例实现了InvocationHandler接口,这个是什么鬼?不就是jdk的反射调用处理接口吗?忘记反射或者不懂反射的同学自行复习或学习。在invoke方法里面通过MapperMethod这个类的execute方法执行相关的方法,来看一下核心调用的庐山真面目:
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.getUserById(1);
这里获得了SqlSessionFactory,接下来就是打开一个session,也就是获得SqlSession,然后就获得一个Mapper实例(mybatis通过反射为我们生成的),然后就可以调用这个mapper接口里的方法了,如果是查询的话那么我们就可以通过对应的实例去接收,整个过程就几行代码,如果我们使用jdbc的话大家应该也知道那个代码量还是非常多的,还要自己new一个实例进行封装,现在这些事mybatis都帮我们做了,接下来我们就看看mybatis怎么帮我们做的。
通过上面的代码可以看到,入口就在build方法,这个方法内部通过XMLConfigBuilder对配置文件进行解析,解析部分就不分析了,主要对xml文件的解析,不懂xml文件解析的话可以先学习一下,我主要分析它如何获取mapper,以及如何封装参数返回给我们。
首先,如何获取mapper,毫无疑问入口就在getMapper方法,跟进去就发现是通过Configuration这个类来获取的,我们上一篇讨论了一些相关的基础类,它里面有一个MapperRegistry类,先在来看看核心是如何实现的,首先这个类里面有一个knownMappers成员变量,保存的是已知的mapper,那什么是已知的mapper?这个就是在刚才解析配置文件的时候生成的,解析配置文件的时候会解析相应的mapper文件,mapper配置里面不是要指定namespace吗?mybatis通过这个namespace生成一个Class对象作为键,值就是MapperProxyFactory<?>,addMapper方法里面有一句:
knownMappers.put(type, new MapperProxyFactory<T>(type));可以看到就是这个时候put进去,type就是一个Class对象。扯远了,回到getMapper方法,看到以下语句:
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);这个获得一个Mapper代理的工厂,这个工厂就是用来生产代理的,生成的代理是用来干嘛的?当然是用来帮我们做事的啦,像对象封装这种事现在有代理帮我们做了。
好了,继续看,mybatis帮我们生成了一个MapperProxy类的实例,可以看到这个实例实现了InvocationHandler接口,这个是什么鬼?不就是jdk的反射调用处理接口吗?忘记反射或者不懂反射的同学自行复习或学习。在invoke方法里面通过MapperMethod这个类的execute方法执行相关的方法,来看一下核心调用的庐山真面目:
public Object execute(SqlSession sqlSession, Object[] args) { 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; }这个result就是我们的查询结果了,这里只是分析了一下执行的过程,并没有深入去分析每一个步骤,比如参数的封装,sql语句解析,。可以看到在上一篇中提到的很多类这里都没有出现,只出现了一个MapperRegistry,希望大家能够有个初步了了解。
相关文章推荐
- mybatis源码解析以及执行的流程
- MyBatis源码解析(一)——执行流程
- Mybatis源码详解之接口方法被执行流程源码解析
- MyBatis源码学习笔记(十)SQL执行流程分析
- ListView.setSelection(int)方法执行流程源码解析(API 21)
- Mybatis源码解析-Mapper执行SQL过程
- Hadoop源码解析-作业执行流程-本地模式
- Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程
- MyBatis源码分析-SQL语句执行的完整流程
- mybatis源码解析 - 通过一个简单查询例子分析流程
- 【原创】angularjs1.3.0源码解析之执行流程
- Mybatis3源码分析(15)-Sql解析执行-Statement初始化和参数设置
- Spinner类setSelection执行流程源码解析
- SpringMVC执行流程及源码解析
- Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程
- Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程
- Mybatis3源码分析(11)-Sql解析执行-BoundSql的加载-1
- Mybatis3源码分析(12)-Sql解析执行-MetaObject
- Flask源码解析:Flask应用执行流程及原理
- mybatis源码分析,sql语句执行的完整流程