Mybatis源码(2)SqlSessionFactory

目标

本文的主要目标是完成SqlSessionFactoryBuilder生成SqlSessionFactory对象的源码阅读,了解Mybatis对mapper.xml文件的查询过程。

1. SqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

通过工厂模式可以生成SqlSessionFactory 对象,这个对象中封装了mappedStatements对象,这个对象中封装了mapper.xml文件解析的sql语句,因此需要分析这个对象的查询过程。

2. 创建SqlSessionFactory流程图

创建SqlSessionFactory的流程图是:

在这里插入图片描述

3. 创建SqlSessionFactory的具体流程

3.1 解析mybatis-config.xml文件创建Configuration对象

先利用Resources的方法生成mybatis-config.xml文件的输入流,然后针对每个标签进行解析。

3.1.1 Debug进入parseConfiguration方法:

在这里插入图片描述
对每个标签进行解析,其中settingsElement方法是设置默认执行器Executor是SimpleExecutor,environmentsElement方法是解析并设置dataSource数据源。

3.1.2 Debug进入mapperElement方法:

在这里插入图片描述
先解析有没有package标签,如果有会扫描这个包下所有的mapper接口并解析相应的mapper.xml文件,如果没有package标签,有resource标签的话会解析mapper.xml文件的位置是在类路径下的mybatis目录下的BlogMapper.xml,并生成输入流,接下来对BlogMapper.xml文件进行解析。

3.2 解析BlogMapper.xml文件

3.2.1 Debug进入configurationElement方法:

在这里插入图片描述

方法的入参已经解析得到mapper标签的内容,在这个方法中会解析mapper.xml的namespace和select等标签。

3.2.2 Debug进入parseStatementNode方法:

在这里插入图片描述

执行创建sql的createSqlSource方法。

3.3 接下来重点分析创建sql的过程

3.3.1 Debug进入parseScriptNode方法:

在这里插入图片描述

判断该sql语句是动态sql还是静态sql,这里是静态sql。

3.3.2 Debug进入parse方法:

在这里插入图片描述
将sql语句的#{author}中的参数名字author单独提取出来,接下来调用handler的handleToken方法将参数名字author添加到parameterMapping这个list集合中。

3.3.3 Debug进入handleToken方法:

在这里插入图片描述
将创建的ParameterMapping对象放入到parameterMappings这个list集合中,同时返回?替换sql的#{author}。其中,会先调用buildParameterMapping方法。

3.3.4 Debug进入buildParameterMapping方法:

在这里插入图片描述
将mapper.xml文件解析出来的接口方法的参数名字放到ParameterMapping中,同样是用工厂模式创建ParameterMapping对象。

3.3.5 Debug进入parseStatementNode方法:

在这里插入图片描述

在创建好sql之后会封装到RawSqlSource,这个对象是StaticSqlSource,这表示它是一个静态sql,这个对象中包含了占位符替换成?的sql语句和parameterMappings这个list集合,它的作用是匹配mapper.xml文件#{author}的参数名字和mapper接口方法的参数名字author然后得到参数值。
XMLStatementBuilder文件的parseStatementNode方法接着创建parameterMap对象为null,resultType对象为Blog对象,resultMap对象为null。

至此,创建sql的分析过程完成。

3.4 创建MappedStatement对象

创建好sql之后在XMLStatementBuilder文件的parseStatementNode方法继续执行。

3.4.1 创建MappedStatement对象

在这里插入图片描述

此时id是mapper.xml文件的id,即接口方法的名字。

3.4.2 Debug进入applyCurrentNamespace方法:

在这里插入图片描述

MapperBuilderAssistant文件的applyCurrentNamespace方法会更新id是mapper.xml文件的namespace.id。

3.4.3 Debug进入addMappedStatement方法:

在这里插入图片描述
更新id是mapper.xml文件的namespace.id之后,利用工厂模式创建MappedStatement对象。

3.4.4 Debug进入MappedStatement的Builder方法:

在这里插入图片描述

创建好sql并将sql封装到SqlSource之后,调用MappedStatement的Builder方法创建MappedStatement对象,其中id值是mapper.xml文件中的namespace.id。

3.4.5 MappedStatement对象放到Configuration中

在这里插入图片描述

mappedStatements是一个map,它是一个StrictMap,存放key是id值,value是MappedStatement对象。
mappedStatements是Configuration的属性,最终MappedStatement对象放到了Configuration对象中。

3.4.6 StrictMap的put源码

在这里插入图片描述

StrictMap如果put数据的时候发现key已经存在就会报错,因此id值必须唯一,并且id值是mapper.xml文件的namespace.id,所以mapper接口方法不能重载。

至此,MappedStatement对象创建完成。

3.5 MapperRegistry对象

MapperRegistry对象mapperRegistry是存放在Configuration对象中的。

3.5.1 Debug进入XMLMapperBuilder的bindMapperForNamespace方法:

在这里插入图片描述

接口的Class类对象存放到map中。

3.5.2 Debug进入MapperRegistry的addMapper方法:

在这里插入图片描述

knownMappers是一个HashMap,key存放接口的Class类对象,value存放MapperProxyFactory工厂类对象,这个工厂类对象的作用是可以生成基于接口的JDK动态代理对象。

至此,MapperRegistry对象创建完成。

3.6 创建SqlSessionFactory

在这里插入图片描述

4. 总结

4.1 关键组件

(1)SqlSessionFactory:SqlSession工厂,它包含了Configuration对象

(2)Configuration:所有数据都存放在Configuration对象中,它包含

  • mappedStatements:它是一个StrictMap,这个map判断如果有相同的key会报错,因此mapper的方法不能重载,mappedStatements的作用是完成mapper.xml文件方法和mapper接口方法的映射

    • key:mapper.xml文件的namespace.id
    • value:MappedStatement对象,它包括
      • id:mapper.xml文件的namespace.id
      • statementType:PREPARED
      • SqlSource对象,它包括:
        • sql:select * from blog where author = ?
        • parameterMappings:parameterMapping是一个List集合,它存放了#{author}中的参数名字author,parameterMapping的作用是匹配mapper.xml文件#{}的参数名字和mapper接口方法的参数名字然后得到参数值
  • mapperRegistry:

    • knownMappers:它是一个ConcurrentHashMap,knownMappers的作用是执行getMapper方法时会根据接口的Class类对象生成JDK动态代理对象
      • key是接口的Class类对象
      • value是MapperProxyRegistry对象

(3)MappedStatement:包括SqlSource等,用来封装sql语句

  • 31
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值