MyBatis 源码分析 - 配置文件解析过程

由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括。本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAliases和typeHandlers等,本文的篇幅也主要在对这三个配置解析过程的分析上。下面,我们来一起看一下本篇文章的目录结构。

MyBatis 源码分析 - 配置文件解析过程

从目录上可以看出,2.3节、2.5节和2.8节的内容比较多。其中2.3节是关于settings配置解析过程的分析,除了对常规的 XML 解析过程分析,本节额外的分析了元信息类MetaClass源码的逻辑。2.5节则是详细分析了别名注册的过程,包含自动注册和手动注册别名等两种方式。2.8节则是详细介绍了类型处理器的注册过程,类型注册逻辑是封装在TypeHandlerRegistry类中的各个register重载方法中。由于重载方法比较多,且互为调用,调用关系比较复杂。为此,我专门画了一张方法调用关系图。这张图在分析类类型处理器注册那一块的源码时,会很有用。

MyBatis 源码分析 - 配置文件解析过程

本文的2.9节主要用于分析 SQL 映射文件的解析过程。由于 SQL 映射文件解析的过程也很复杂,所以这里把2.9节独立成文,后续会进行更新。至于其他的章节,没什么太复杂的东西,就不一一叙述了。

以上就是 MyBatis 配置文件解析过程的速览,如果大家对以上所说内容比较熟悉了,那就不用往下看了。如果不了解,或是有兴趣的话,不妨阅读一下。本篇文章行文较长,除了对常规的 XML 解析过程进行分析,还额外分析了一些源码。如果能掌握本文所分析内容,我相信可以对 MyBatis 有更深入的了解。好了,其他的就不多说了,进入正题吧。

1.简介

在上一篇文章中,我介绍了 MyBatis 的一些基础知识,用于为本文及后续的源码分析文章进行铺垫。经过前面的铺垫,我觉得是时候后分析一下 MyBatis 源码了。在本篇文章中,我将从 MyBatis 解析配置文件的过程着手进行分析。并会在分析的过程中,向大家介绍一些配置的使用方式和用途。MyBatis 的配置比较丰富,很难在一篇文章中把所有配置的解析过程分析完。所以关于配置文件的解析,这里会分两篇文章进行讲解。本篇文章将会分析诸如settings,typeAliases以及typeHandlers等标签的解析过程。下一篇文章则会重点介绍 SQL 映射文件的解析过程。本系列文章所分析的源码版本为3.4.6,是 MyBatis 最新的版本。好了,其他的就不多说了,下面进入源码分析阶段。

2.配置文件解析过程分析 2.1 配置文件解析入口

在单独使用 MyBatis 时,第一步要做的事情就是根据配置文件构建SqlSessionFactory对象。相关代码如下:

String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

首先,我们使用 MyBatis 提供的工具类 Resources 加载配置文件,得到一个输入流。然后再通过 SqlSessionFactoryBuilder 对象的build方法构建 SqlSessionFactory 对象。所以这里的 build 方法是我们分析配置文件解析过程的入口方法。那下面我们来看一下这个方法的代码:

// -☆- SqlSessionFactoryBuilder public SqlSessionFactory build(InputStream inputStream) { // 调用重载方法 return build(inputStream, null, null); } public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { // 创建配置文件解析器 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); // 调用 parse 方法解析配置文件,生成 Configuration 对象 return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Configuration config) { // 创建 DefaultSqlSessionFactory return new DefaultSqlSessionFactory(config); }

从上面的代码中,我们大致可以猜出 MyBatis 配置文件是通过XMLConfigBuilder进行解析的。不过目前这里还没有非常明确的解析逻辑,所以我们继续往下看。这次来看一下 XMLConfigBuilder 的parse方法,如下:

// -☆- XMLConfigBuilder public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; // 解析配置 parseConfiguration(parser.evalNode("/configuration")); return configuration; }

到这里大家可以看到一些端倪了,注意一个 xpath 表达式 - /configuration。这个表达式代表的是 MyBatis 的<configuration/>标签,这里选中这个标签,并传递给parseConfiguration方法。我们继续跟下去。

private void parseConfiguration(XNode root) { try { // 解析 properties 配置 propertiesElement(root.evalNode("properties")); // 解析 settings 配置,并将其转换为 Properties 对象 Properties settings = settingsAsProperties(root.evalNode("settings")); // 加载 vfs loadCustomVfs(settings); // 解析 typeAliases 配置 typeAliasesElement(root.evalNode("typeAliases")); // 解析 plugins 配置 pluginElement(root.evalNode("plugins")); // 解析 objectFactory 配置 objectFactoryElement(root.evalNode("objectFactory")); // 解析 objectWrapperFactory 配置 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); // 解析 reflectorFactory 配置 reflectorFactoryElement(root.evalNode("reflectorFactory")); // settings 中的信息设置到 Configuration 对象中 settingsElement(settings); // 解析 environments 配置 environmentsElement(root.evalNode("environments")); // 解析 databaseIdProvider,获取并设置 databaseId 到 Configuration 对象 databaseIdProviderElement(root.evalNode("databaseIdProvider")); // 解析 typeHandlers 配置 typeHandlerElement(root.evalNode("typeHandlers")); // 解析 mappers 配置 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzyxw.html