搭建源码环境
在这里我提一下,在早期Mybatis版本中,Dao开发方式都是有Mapper接口和其实现类的,实现类是需要我们自己编写的,后来Mybatis使用JDK动态代理针对Mapper接口做了代理,替我们实现了实现类; 但是其底层也是使用了Mapper接口的实现类,不可能说只有一个即可就能和JDBC进行通讯 ! 其基础环境搭建可参照官方教程
POM依赖 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> 测试SQL CREATE TABLE `user` ( `id` int(10) NOT NULL AUTO_INCREMENT, `username` varchar(10) NOT NULL, `password` varchar(52) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 Mybatis全局配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property value="com.mysql.jdbc.Driver"/> <property value="jdbc:mysql://localhost:3306/test"/> <property value="root"/> <property value="jimisun"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration> UserMapper接口 public interface UserMapper { User selectUser(Integer id); } UserMapper配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="user"> <select resultType="com.jimisun.mybatis.domain.User"> select * from user where id = #{id} </select> </mapper> User实体 public class User { private int id; private String username; private String password; getter and setter ..... } Main方法 public static void main(String[] args) throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("user.selectUser", 2); System.out.println(user.toString()); } 快速进入Debug跟踪我们可以在此处打上断点,Debug模式启动进入断点,再按F7跟踪入其方法
源码分析准备在进行Mybatis的初始化过程之前,我们需要把整个大纲拎出来放在前面,让大家能够有所了解,然后在进行每个步骤的时候心里有个大概;
什么是Mybatis的初始化过程?
从代码上来看 "SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);" 这行代码就是执行的是Mybatis的初始化操作,这个操作通常在应用中只会操作一次,构建完成SqlSessionFactory就不再使用,而SqlSessionFactory会跟随整个应用生命周期;
从应用阶段上来说 : Mybatis根据全局XML配置文件生成SqlSessionFactory的过程就是Mybatis的初始化过程.
浅析一词含义
既然标题为浅析某某....相比大家也能看出说明本章不会深度挖掘底层代码,我个人认为浅析一次的主要意义是 ""能够快速地在我们心中建立底层源码的架构图,快速浏览代码,与概念进行核对 "",当然也不包含某些大牛谦虚的说法哈~~ 在这里提的主要目的是,本次浅析Mybatis是快速浏览代码; 稍后会出新的篇章对核心方法进行剖析
Mybatis初始化过程中的主要步骤
将全局配置文件XML解析到Configuration对象
将映射配置文件XML解析到Configuration的mapperRegistry对象
将映射配置文件XML中的声明(Statement)解析成MappedStatement对象存入Configuration对象的mappedStatements集合中
最后将Configuration最为参数构建DefaultSqlSessionFactory对象
源码分析 第一步: 将全局配置文件XML加载到Configuration对象 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); parser.parse();主要功能 : 将全局配置文件中的配置加载到一个Configuration对象的属性中
这是第一步,我们从Main方法的new SqlSessionFactoryBuilder().build(inputStream)进入断点,可以看到在构建完毕SqlSessionFactoryBuilder对象后由调用了重载的build方法
//SqlSessionFactoryBuilder的构造方法 public SqlSessionFactoryBuilder() { } //build方法 public SqlSessionFactory build(InputStream inputStream) { return this.build((InputStream)inputStream, (String)null, (Properties)null); } //build方法(重载) public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { SqlSessionFactory var5; try { //第一步: 创建XML配置构建器,用来解析全局XML文件内容 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); var5 = this.build(parser.parse()); } catch (Exception var14) { throw ExceptionFactory.wrapException("Error building SqlSession.", var14); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException var13) { } } return var5; }