按功能模块分:
- sql解析阶段
- sql执行阶段
先看解析阶段
@BeforeAll
static void initDatabase() throws Exception {
try (Reader reader = Resources.getResourceAsReader("mybatis-config.xml")) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
}
方法的调用链:
【SqlSessionFactoryBuilder】#bulid
|--【XMLConfigBuilder】#new
|--【XMLConfigBuilder】#parse
|--parseConfiguration (注释 同一个类中的方法调用,省去前面的类名部分)
|---xxxxxx
|---environmentsElement
|---mapperElement
|--【XMLMapperBuilder】#new
|--【XMLMapperBuilder】#parse
|--configurationElement
|--xxxxxx
|--buildStatementFromContext
|--【XMLStatementBuilder】#new
|--【XMLStatementBuilder】#parseStatementNode
|--【XMLLanguageDriver】#createSqlSource
|--【XMLScriptBuilder】#new
|--【XMLScriptBuilder】#parseScriptNode
|---parseDynamicTags
|---DynamicSqlSource#new
|---RawSqlSource#new
|--【MapperBuilderAssistant】#addMappedStatement
上面只是冰山一角,只列出了解析Mapper的Resource这种方式的。一共四种解析Mapper的方式。
然后看sql的执行阶段:
//3、获取mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//4、执行数据库操作,并处理结果集
return userMapper.selectOne("10");
方法的调用链:
【DefaultSqlSession】#getMapper
|--【Configuration】#getMapper
|--【MapperRegistry】#getMapper
|--knownMappers.get(type) -->MapperProxyFactory(代表返回值类型)
|--【MapperProxyFactory】#newInstance
|--【MapperProxy】#new
|--newInstance
|--【Proxy】#newProxyInstance
上面是getMapper的调用链,由此看出走的jdk的动态代理
下面看selectOne这个方法的调用链,jdk动态代理,直接看我们MapperProxy(实现了InvocationHandler接口)的invoke方法。
【MapperProxy】#invoke
|--cachedInvoker-->MapperMethodInvoker(PlainMethodInvoker是实现类)(代表返回类型)
|--【PlainMethodInvoker】#invoke
|--【MapperMethod】#execute
|--【MethodSignature】#convertArgsToSqlCommandParam
|--【DefaultSqlSession】#selectOne
|--selectList
|--【Configuration】#getMappedStatement
|--【CachingExecutor】#query(这儿根据配置,这是开启二级缓存时)
|--【MappedStatement】#getBoundSql
|--createCacheKey
|--query
|--tcm.getObject (查二级缓存,不存在则走下面方法)
|--【BaseExecutor】#query
|--localCache.getObject (从一级缓存查,没有则走下面方法)
|--queryFromDatabase
|--【SimpleExecutor】doQuery
|--【MappedStatement】#getConfiguration
|--【Configuration】newStatementHandler
|--prepareStatement (建立连接,statement对象创建,参数赋值)
|--getConnection
|--【RoutingStatementHandler】#prepare
|--【PreparedStatementHandler】prepare
|--【RoutingStatementHandler】#parameterize
|--【PreparedStatementHandler】#parameterize
|--【RoutingStatementHandler】#query
|--【PreparedStatementHandler】#query
|--【PreparedStatement】#execute
|--【DefaultResultSetHandler】#handleResultSets (进行jdbc结果集转java类型结果集操作)
上面的总结相当于建立了一个目录,在这个目录下,如果想要看具体的细节,可以看之前的文章。
比如:
MyBatis源码的学习(5)—设计模式的使用
MyBatis源码的学习(10)—高版本的Mapper.XML中为何不能使用#{0},#{1}操作?
MyBatis源码的学习(11)—Mybatis二级缓存默认LRU算法的分析
MyBatis源码的学习(16)—拦截器为何不能拦截Executor中6个参数的query方法
MyBatis源码的学习(18)—如何对statement对象进行参数赋值操作的?
MyBatis源码的学习(19)—如何将jdbc的返回结果resultSet处理为我们想要的java类型
MyBatis源码的学习(22)—关于#和
的
区
别
,
简
单
类
型
的区别,简单类型
的区别,简单类型中只能用value吗??