整个XML解析概览
# builder初始化
>org.apache.ibatis.session.Configuration#Configuration() 初始化内置别名
>org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties)
>org.apache.ibatis.builder.xml.XMLConfigBuilder#parse
>org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration 解析配置文件
>org.apache.ibatis.builder.xml.XMLConfigBuilder#propertiesElement 解析 properties 标签,定义key、value配置
>org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement 安装mapper路径配置进行解析,构建 XMLMapperBuilder mapperParser,每一个mapper文件对应一个XMLMapperBuilder
>org.apache.ibatis.builder.xml.XMLMapperBuilder#parse
>org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement 开始解析单个mapper
>org.apache.ibatis.builder.xml.XMLMapperBuilder#cacheElement cache配置,如果自定义缓存需要实现org.apache.ibatis.cache.Cache接口
>org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElement(org.apache.ibatis.parsing.XNode, java.util.List<org.apache.ibatis.mapping.ResultMapping>, java.lang.Class<?>)
解析resultMap,最终构建成ResultMapResolver,里面每一行result封装成ResultMapping
>org.apache.ibatis.builder.xml.XMLMapperBuilder#sqlElement(java.util.List<org.apache.ibatis.parsing.XNode>, java.lang.String) Map<String, XNode> sqlFragments; 解析sql标签
>org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode "select|insert|update|delete" 标签解析方法
>org.apache.ibatis.session.Configuration#getLanguageDriver 获取LanguageDriver, 默认为XMLLanguageDriver
> org.apache.ibatis.scripting.xmltags.XMLScriptBuilder#parseScriptNode 构建SqlSource, 如果是非动态sql,也就是未使用<if>等标签,则会构建则会构建RawSqlSource,否则构建为DynamicSqlSource,区别在于RawSqlSource会对#进行预处理,更快
> org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement(java.lang.String, org.apache.ibatis.mapping.SqlSource, org.apache.ibatis.mapping.StatementType, org.apache.ibatis.mapping.SqlCommandType, java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.Class<?>, java.lang.String, java.lang.Class<?>, org.apache.ibatis.mapping.ResultSetType, boolean, boolean, boolean, org.apache.ibatis.executor.keygen.KeyGenerator, java.lang.String, java.lang.String, java.lang.String, org.apache.ibatis.scripting.LanguageDriver, java.lang.String)
构建 MappedStatement,构建完成后 put到org.apache.ibatis.session.Configuration#mappedStatements中
>org.apache.ibatis.builder.xml.XMLMapperBuilder#bindMapperForNamespace 绑定mapper接口
> org.apache.ibatis.binding.MapperRegistry#addMapper 解析mapper接口,解析完成后会放入到knownMappers的map中,key为class type, value为MapperProxyFactory
> org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse 注解解析
parse
public Configuration parse() {
// 防止二次加载
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
// /configuration 为xml配置的 根节点。
// parseConfiguration 加载自己所需的配置
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
parsed是一个全局变量,默认为false。
parseConfiguration是具体的解析方法
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
// 自定义配置属性 这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。
propertiesElement(root.evalNode("properties"));
//这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项的意图、默认值等。
Properties settings = settingsAsProperties(root.evalNode("settings"));
// vfsImpl ?? 不太清楚撒玩意 VFS含义是虚拟文件系统;主要是通过程序能够方便读取本地文件系统、FTP文件系统等系统中的文件资源。
// 自定义VFS实现,VFS是Mybatis 虚拟的一层文件系统,不用在意底层,可以拓展支持其他实现支持资源访问。
loadCustomVfs(settings);
// 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
loadCustomLogImpl(settings);
// 类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
typeAliasesElement(root.evalNode("typeAliases"));
// 插件。MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。
pluginElement(root.evalNode("plugins"));
// 对象工厂(objectFactory)
// MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。
// 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。
// 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。
objectFactoryElement(root.evalNode("objectFactory"));
// 这参数官方文档没介绍啊
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
// 这个参数也是
reflectorFactoryElement(root.evalNode("reflectorFactory"));
// 根据读取的 参数 进行初始化。
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
// 环境配置
environmentsElement(root.evalNode("environments"));
// 数据库厂商标识,如果官方不支持的数据库 通过这个来自己拓展????
// todo 待考证
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
// 类型处理器(typeHandlers)
typeHandlerElement(root.evalNode("typeHandlers"));
// mapper 处理
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
这段代码非常直观,一眼就能看出,标签对应的解析方法。