mybatis底层源码分析之--配置文件读取和解析

现在企业级开发中ssm是很常见的技术标配,mybatis比hibernate轻量了很多,而且学习成本相对较低,简单易上手。

  那么,问题来了,简单好用的mybatis底层到底是如何实现的呢?都使用了什么原理呢?

  为了深入的了解底层原理呢,写了几段简单的代码结合debug,开始学习底层咯,直接先上代码。

public class XmlReaderTest {
    @Test
    public void mybatisXmlReaderTest() {
        String resourceXml = "mybatis-test-config.xml";
        SqlSessionFactory factory = null;
        SqlSession sqlSession = null;
        try {
            Reader reader = Resources.getResourceAsReader(resourceXml);
            factory = new SqlSessionFactoryBuilder().build(reader);
            sqlSession = factory.openSession();
            List<Student> list = sqlSession.selectList("getStudentInfo","lily");
            System.out.println(list.size()+">>>"+list.get(0).getAddress());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
    }
}
View Code
<?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 id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/logistics?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/springapp/mybatis/StudentMapper.xml"/>
        <mapper resource="com/springapp/mybatis/TeacherMapper.xml"/>
    </mappers>

</configuration>
View Code

首先是读取mybatis的配置文件,创建工程类,获得session,调用SqlSession里面的方法进行数据库的相关操作。

factory = new SqlSessionFactoryBuilder().build(reader);
主要看后面的build()方法,返回DefaultSqlSessionFactory对象:
其实通过build()方法最终调的是这个方法:
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
在这个方法中使用了配置文件的解析类xmlconfigbuilder,重点看这一句:
 return build(parser.parse());  进入xmlconfigbuilder的parse()方法进一步查看:
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
返回的是一个Configuration对象,其中
parser.evalNode("/configuration"),解析配置文件,返回指定节点的内容。
内容如下:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/logistics?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/springapp/mybatis/StudentMapper.xml"/>
<mapper resource="com/springapp/mybatis/TeacherMapper.xml"/>
</mappers>
</configuration>
View Code

它的外层方法parseConfiguration(),进行具体的解析configuration下的子节点,并给configuration的对应变量赋值。

重点关注其中的:

environmentsElement(root.evalNode("environments")); //相当于jdbc配置数据源,以及事务的配置
mapperElement(root.evalNode("mappers"));//解析sql映射文件


最后附上流程图:





原文地址:https://www.cnblogs.com/tom-plus/p/5576314.html