Mybatis源码解读
源码关键词
阅读源码中一些关键字,有利于快速理解类的意思:
Resolver:解析器
此接口表示用于名称解析的“中间上下文”。
Resolver接口包含由上下文实现的方法,这些方法不支持Context的子类型,但是可以充当中间上下文以实现解析目的。
传递给任何方法的Name参数归调用者所有。 服务提供者将不会修改该对象或保留对其的引用。 调用者拥有任何方法返回的ResolveResult对象。 调用者可以随后对其进行修改; 服务提供商可能不会。
Handler:控制器
常被用作线程间传递消息的组件,而且还可以用于跨进程
Parser解析器
parser,一般是指把某种格式的文本(字符串)转换成某种数据结构的过程。最常见的 parser,是把程序文本转换成编译器内部的一种叫做“抽象语法树”(AST)的数据结构。也有简单一些的 parser,用于处理 CSV,JSON,XML 之类的格式。
Statement声明
用于执行静态SQL语句并返回其产生的结果的对象。
statements就像一个车,,当从数据库中取数据的时候首先要建立一个connection,这个东西是java程序和数据库的一个连接,可以把connection想成一条路,然后你怎么把东西拉回来,就要用到这个statements,把东西拉回来之后,再组装起来,放到一个resultSet中
Mybatis结构图
获取SqlSessionFactory对象
1.通过parseConfiguration()在configuration标签中设置 properties、settings、environments等属性标签
将所有的配置信息放在了Configuration对象中
2.XMLConfigBuilder会调用XPathParser解析所有的Xml文件,然后调用XMLMapperEntityResolver来解析实体类接口的XXXMapper.xml文件(分析其中的增删改查标签),解析是SAX解析.
<select id=""resultType="等属性是通过parseStatementNode()解析的>
会将XxxMapper.xml中的<select>等标签解析成 MappedStatement对象
即MappedStatement对 就是<select>等标签
3.MappedStatement、environment等信息都存在于Configuration中,基本所有的配置信息、增删改标签全部存在于Configuration中
4.最后将将这个config(Configuration对象)传递给DefaultSqlSessionFactory(SqlSessionFactory接口的实现类),通过返回一个DefaultSqlSessionFactory的对象,然后SqlSessionFactory对象通过build方法产生一个SqlSessionFactory对象
时序图:
获取SqlSession对象
1.sessionFactory.openSession()之后,会去调用DefaultSqlSessionFactory去加载配置,主要是一些默认的配置,例如DefaultExecutorType(默认的值是SIMPLE),还会去调用Environment来加载一些事物配置以及数据配置,然后返回一个执行器(Executor),然后将configuration, executor传递给DefaultSqlSession,创造一个SqlSession对象返回.
2.configuration.newExecutor(tx, execType) ========>SimpleExecutor
根据不同的类型execType,产生不同的Executor,并且会对执行器进行拦截操作
3.executor = (Executor) interceptorChain.pluginAll(executor);
通过装饰模式,将刚产生的executor 包装成一个更加强大的 executor。
作用:如果要给MyBatis写自己的插件,就可以通过拦截器实现。
插件开发:
1、写插件
2、放入拦截器
返回DefaultSqlSession(configuration,executor,事务),最终得到SqlSession对象
SqlSession===> openSession() =>openSessionFromDataSource()=>DefaultSqlSession对象
SqlSession===> DefaultSqlSession对象 ===>执行SQL
FileInputSTream("d://abc.txt")===>InputSTream,字符串->变成对象
时序图:
获取XxxMapper对象
执行增删改查=>MapperProxy/invoke()=>InvocationHandler :JDK动态代理接口
过程用到了动态代理模式:
增删改查 =>代理对象 (MapperProxy对象)=>代理对象 帮我们“代理执行” 增删改查
XxxMapper代理对象: MapperProxy对象
mapperMethod.execute(sqlSession,args) :实际调用增删改查的方法 ,依靠了sqlSession中的configuration和 executor..
处理增删改查方法的参数:method.convertArgsToSqlCommandParam(args);: 如果參數是0个,reutrun null ;如果参数是1,返回第一个 ; 如果有多个参数 放入map中
查询方法:selectOne() ===>selectList() : configuration.getMappedStatement() 即获取到用于增删改查的对象
boundSql :将我们写的SQL 和 参数值进行了拼接后的对象,即最终能被真正执行的SQL
执行SQL 是通过Executor
如果缓存中没有要查询的内容,则进入数据库 真实查询:queryFromDatabase()
mybatis使用的jdbc對象是PreparedStatement
底层执行增删改查:PreparedStatement的execute()
MyBatis底层在执行CRUD时 可能会涉及到四个处理器:StatementHandler ParameterHandler TypeHandler ResultSetHandler
XxxMapper:
SqlSession(configuration,executor,事务)、代理接口的对象(MapperInterface)、methodCache(存放查询缓存, 底层是CurrentHashMap)
(代理接口中的方法、mapper.xml中的<select>等标签)