这篇文章咱们来深刻阅读下Mybatis的源码,但愿之后能够对底层框架不那么畏惧,学习框架设计中好的思想;
上面这两幅图来源于网络,不过画的很好,基本说明了Mybatis的架构流程。java
说明:node
Mybatis配置文件mysql
SqlSessionFactory程序员
SqlSessionsql
Executor执行器数据库
MappedStatement编程
Executor设计模式
MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护api
StatementHandler缓存
封装了JDBC Statement操做,负责对JDBC statement 的操做,如设置参数、将Statement结果集转换成List集合。
ParameterHandler
负责对用户传递的参数转换成JDBC Statement 所须要的参数
ResultSetHandler
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler
负责java数据类型和jdbc数据类型之间的映射和转换
SqlSource
负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回BoundSql表示动态生成的SQL语句以及相应的参数信息
SqlSessionFactoryBuilder#build 构建SqlSessionFactory XMLConfigBuilder#parse 全局配置文件解析,封装成Configuration对象 #parseConfiguration 从根路径开始解析,加载的信息设置到Configuration对象中 #mapperElement 解析mapper映射文件 XMLMapperBuilder#parse 具体解析mapper映射文件 SqlSessionFactoryBuilder#build:建立SqlSessionFactory接口的默认实现类
1.SqlSessionFactoryBuilder建立SqlsessionFactory时,须要传入一个Configuration对象。 2.XMLConfigBuilder对象会去实例化Configuration。 3.XMLConfigBuilder对象会去初始化Configuration对象。 经过XPathParser去解析全局配置文件,造成Document对象 经过XPathParser去获取指定节点的XNode对象。 解析Xnode对象的信息,而后封装到Configuration对象中
|--SqlSessionFactoryBuilder |--XMLConfigBuilder |--XPathParser |--Configuration
XMLConfigBuilder#mapperElement:解析全局配置文件中的<mappers>标签 |--XMLMapperBuilder#构造方法:专门用来解析映射文件的 |--XPathParser#构造方法: |--XPathParser#createDocument():建立Mapper映射文件对应的Document对象 |--MapperBuilderAssistant#构造方法:用于构建MappedStatement对象的 |--XMLMapperBuilder#parse(): |--XMLMapperBuilder#configurationElement:专门用来解析mapper映射文件 |--XMLMapperBuilder#buildStatementFromContext:用来建立MappedStatement对象的 |--XMLMapperBuilder#buildStatementFromContext |--XMLStatementBuilder#构造方法:专门用来解析MappedStatement |--XMLStatementBuilder#parseStatementNode: |--MapperBuilderAssistant#addMappedStatement:建立 MappedStatement对象 |--MappedStatement.Builder#构造方法 |--MappedStatement.Builder#build方法:建立MappedStatement对象,并存储 到Configuration对象中
|--XMLConfigBuilder |--XMLMapperBuilder |--XPathParser |--MapperBuilderAssistant |--XMLStatementBuilder |--MappedStatement
XMLLanguageDriver#createSqlSource 建立SqlSource,解析SQL,封装SQL语句(出参数绑定)和入参信息 XMLScriptBuilder 构造函数:初始化动态SQL中的节点处理器集合 XMLScriptBuilder#parseScriptNode #parseDynamicTags 解析select\insert\ update\delete标签中的SQL语句,最终将解析到的SqlNode封装到MixedSqlNode中的List集合中 DynamicSqlSource 构造方法:若是SQL中包含${}和动态SQL语句,则将SqlNode封装到DynamicSqlSource RawSqlSource 构造方法:若是SQL中包含#{},则将SqlNode封装到RawSqlSource中,并指定parameterType SqlSourceBuilder#parse ParameterMappingTokenHandler 构造方法 GenericTokenParser#构造方法,指定待分析的openToken和closeToken并指定处理器 GenericTokenParser#parse 解析#{} ParameterMappingTokenHandler#handleToken 处理token(#{}/${}) #buildParameterMapping 建立ParameterMapping对象 StaticSqlSource 构造方法,将解析以后的sql信息,封装到StaticSqlSource 对象
|--XMLLanguageDriver |--XMLScriptBuilder |--SqlSource |--SqlSourceBuilder
|--DefaultSqlSession#getMapper:获取Mapper代理对象 |--Configuration#getMapper:获取Mapper代理对象 |--MapperRegistry#getMapper:经过代理对象工厂,获取代理对象 |--MapperProxyFactory#newInstance:调用JDK的动态代理方式,建立Mapper代理
DefaultSqlSession#selectList CachingExecutor#query BaseExecutor#query 委托给BaseExecutor执行 #queryFromDatabase SimpleExecutor#doQuery 执行查询 Configuration#newStatementHandler 建立路由功能的StatementHandler,根据MappedStatement中的StatementType SimpleExecutor#prepareStatement 设置PreapreStatement 的参数 BaseExecutor#getConnection 获取数据库链接 BaseStatementHandler#prepare 建立Statement PrepareStatement、Statement、CallableStatement) PreparedStatementHandler#parameterize 设置参数 PreparedStatementHandler#query 执行SQL语句(已经设置过参数),而且映射结果集 com.mysql.jdbc.PreparedStatement#execute 调用JDBC的api执行Statement DefaultResultSetHandler#handleResultSets 处理结果集
|--DefaultSqlSession |--Executor |--CachingExecutor |--BaseExecutor |--SimpleExecutor |--StatementHandler |--RoutingStatementHandler |--PreparedStatementHandler |--ResultSetHandler |--DefaultResultSetHandler
MappedStatement#getBoundSql DynamicSqlSource#getBoundSql SqlSourceBuilder#parse 执行解析:将带有#{}的SQL语句进行解析,而后封装到StaticSqlSource中 GenericTokenParser #构造方法,指定待分析的openToken和closeToken,并指定处理器 GenericTokenParser#parse 解析SQL语句,处理openToken和closeToken中的内容 ParameterMappingTokenHandler#handleToken 处理token(#{}/${}) #buildParameterMapping 建立 ParameterMapping对象 StaticSqlSource#构造方法 : 将解析以后的SQL信息,封装到StaticSqlSource |--RawSqlSource#getBoundSql |--StaticSqlSource#getBoundSql |--BoundSql#构造方法:将解析后的sql信息、参数映射信息、入参对象组合到BoundSql对象中
|--PreparedStatementHandler#parameterize:设置PreparedStatement的参数 |--DefaultParameterHandler#setParameters:设置参数 |--BaseTypeHandler#setParameter: |--xxxTypeHandler#setNonNullParameter:调用PreparedStatement的setxxx方法
|--DefaultResultSetHandler#handleResultSets |--DefaultResultSetHandler#handleResultSet |--DefaultResultSetHandler#handleRowValues |--DefaultResultSetHandler#handleRowValuesForSimpleResultMap |--DefaultResultSetHandler#getRowValue |--DefaultResultSetHandler#createResultObject:建立映射结果对象 |--DefaultResultSetHandler#applyAutomaticMappings |--DefaultResultSetHandler#applyPropertyMappings
基本上Mybatis的流程就是这样了,其中还有不少实现细节暂时看不太懂。 我认为学习框架源码分为两步:
目前第一步尚有问题,须要多走几遍源码,加深下理解,一块儿加油~~