【源码篇】聊聊源码mybatis(构建加载初始化源码分析)


在这里插入图片描述

该节内容主要将Mybatis初始化内容,回顾下我们第一节的核心重点图。

在这里插入图片描述

举个case:Mybatis初始化的加载过程时序图

在这里插入图片描述

3.1、XML的配置解析示例

3.1.1、mybatis-config.xml的使用示例

//1、xml的协议头
<?xml version="1.0" encoding="UTF-8" ?>
//2、mybatis对于xml,Configuration配置文件的约束协议
  <!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
//3、全局配置对象
<configuration>
  //3.1.1、数据源配置1:通过属性注入数据源
  <properties resource="org/apache/ibatis/databases/blog/blog-derby.properties"/>
  //3.1.2、数据源配置2:通过直接配置
  //3.2、全局配置对象的属性
  <settings>
    //是否开启缓存
    <setting name="cacheEnabled" value="true"/>
    //是否开启懒加载
    <setting name="lazyLoadingEnabled" value="false"/>
    //是否允许返回多个结果集
    <setting name="multipleResultSetsEnabled" value="true"/>
    //是否使用驼峰标示属性
    <setting name="useColumnLabel" value="true"/>
    //是否使用生成主键策略
    <setting name="useGeneratedKeys" value="false"/>
    //默认的执行器类型
    <setting name="defaultExecutorType" value="SIMPLE"/>
    //默认的会话超时时间单位s
    <setting name="defaultStatementTimeout" value="25"/>
  </settings>
  //3.3、实体对象别名映射
  <typeAliases>
    <typeAlias alias="Author" type="org.apache.ibatis.domain.blog.Author"/>
  </typeAliases>
  //3.3、指定类型处理器
  <typeHandlers>
    <typeHandler javaType="String" jdbcType="VARCHAR" handler="org.apache.ibatis.builder.CustomStringTypeHandler"/>
  </typeHandlers>
  //3.4、对象工厂
  <objectFactory type="org.apache.ibatis.builder.ExampleObjectFactory">
    <property name="objectFactoryProperty" value="100"/>
  </objectFactory>
  //3.5、配置会话拦截插件
  <plugins>
    <plugin interceptor="org.apache.ibatis.builder.ExamplePlugin">
      <property name="pluginProperty" value="100"/>
    </plugin>
  </plugins>
  //3.6、配置环境变量: MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
  <environments default="development">
    //3.6.1、环境配置变量可以通过ID来区分dev-uat-pre-pro
    <environment id="development">
       //3.6.1.1、事务管理器
      <transactionManager type="JDBC">
        <property name="" value=""/>
      </transactionManager>
      //3.6.1.2、数据源配置
      <dataSource type="UNPOOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  //3.7、mapper接口配置,包含了 SQL 代码和映射定义信息
  <mappers>
    <mapper resource="org/apache/ibatis/builder/AuthorMapper.xml"/>
  </mappers>

</configuration>

3.1.2、Mapper.xml的使用示例

//1、xml的定义
<?xml version="1.0" encoding="UTF-8" ?>
//2、mapper协议的约束
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
//3、映射类路径的mapper,实际上是和对应的java类绑定
<mapper namespace="org.apache.ibatis.domain.blog.mappers.AuthorMapper">
//4、mapper接口方法:根据主键ID查询返回结果map的
	<parameterMap id="selectAuthor" type="org.apache.ibatis.domain.blog.Author">
		<parameter property="id" />
	</parameterMap>
//5、mapper接口方法:对于实体对象和数据库字段的映射情况
	<resultMap id="selectAuthor" type="org.apache.ibatis.domain.blog.Author">
    //字段列和对象属性的映射
		<id column="id" property="id" />
		<result property="username" column="username" />
		<result property="favouriteSection" column="favourite_section" />
	</resultMap>
//6、mapper接口方法:包含嵌套的对象属性字段映射情况
	<resultMap id="selectImmutableAuthor" type="org.apache.ibatis.domain.blog.ImmutableAuthor">
    //参数和Java类型映射
		<constructor>
			<idArg column="id" javaType="_int" />
			<arg column="username" javaType="string" />
			<arg column="favourite_section" javaType="org.apache.ibatis.domain.blog.Section" />
		</constructor>
	</resultMap>
//7、mapper接口方法:查询所有结果
	<select id="selectAllAuthors" resultType="org.apache.ibatis.domain.blog.Author">
		select * from author
	</select>
//8、mapper接口方法:查询返回set集
	<select id="selectAllAuthorsSet" resultType="org.apache.ibatis.domain.blog.Author">
		select * from author
	</select>
//9、mapper接口方法:查询返回list集合
	<select id="selectAllAuthorsLinkedList" resultType="org.apache.ibatis.domain.blog.Author">
		select * from author
	</select>
//10、mapper接口方法:查询返回数组
	<select id="selectAllAuthorsArray" resultType="org.apache.ibatis.domain.blog.Author">
		select * from author
	</select>
//11、mapper接口方法:查询只返回部分参数
	<select id="selectAuthorLinkedHashMap" resultType="java.util.LinkedHashMap">
		select id, username from author where id = #{value}
	</select>
//12、mapper接口方法:查询绑定外部传入参数
	<select id="selectAuthor" parameterMap="selectAuthor" resultMap="selectAuthor">
		select id, username, password, email, bio, favourite_section
		from author where id = ?
	</select>
//13、mapper接口方法:查询指定入参类型的参数
	<select id="selectAuthorWithInlineParams" parameterType="int"
		resultType="org.apache.ibatis.domain.blog.Author">
		select * from author where id = #{id}
	</select>
//14、mapper接口方法:插入实体对象映射
	<insert id="insertAuthor" parameterType="org.apache.ibatis.domain.blog.Author">
		insert into Author (id,username,password,email,bio)
		values (#{id},#{username},#{password},#{email},#{bio})
	</insert>
//15、mapper接口方法:更新实体对象映射
	<update id="updateAuthor" parameterType="org.apache.ibatis.domain.blog.Author">
		update Author
		set username=#{username,
		javaType=String},
		password=#{password},
		email=#{email},
		bio=#{bio}
		where id=#{id}
	</update>
//16、mapper接口方法:删除实体根据主键ID
	<delete id="deleteAuthor" parameterType="int">
		delete from Author where id = #{id}
	</delete>

//17、mapper接口方法:有选择更新字段
	<update id="updateAuthorIfNecessary" parameterType="org.apache.ibatis.domain.blog.Author">
		update Author
		<set>
			<if test="username != null">username=#{username},</if>
			<if test="password != null">password=#{password},</if>
			<if test="email != null">email=#{email},</if>
			<if test="bio != null">bio=#{bio}</if>
		</set>
		where id=#{id}
	</update>
//18、mapper接口方法:根据指定的条件进行查询
	<select id="selectWithOptions" resultType="org.apache.ibatis.domain.blog.Author"
		fetchSize="200" timeout="10" statementType="PREPARED" resultSetType="SCROLL_SENSITIVE" flushCache="false" useCache="false">
		select * from author
	</select>
</mapper>

3.1.3、代码中XML的配置解析使用示例

3.1.3.1、从 XML 中构建 SqlSessionFactory

根据Mybatis核心设计图其实可以观察到,整个Mybatis的核心在于一个SqlSession的一系列操作:实体对象和SQL的绑定,执行会话,结果集处理。而SqlSession的管理则来自于SqlSessionFactory,SqlSessionFactory是可以通过SqlSessionFactoryBuilder获得构建。如何构建出符合用户的SqlSessionFactory,则依赖于我们上面提到的Configuration 实例(Mybatis-config.xml)。

⚠️:强调下重点:每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的,SqlSessionFactory 的实例是通过SqlSessionFactoryBuilder从Configuration 实例(Mybatis-config.xml)构建出来的。

​ 从 XML 文件中构建 SqlSessionFactory 的实例非常简单,可以使用类路径下的资源文件进行配置。也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类可以通过它来获取资源输入流(可以参考之后的源码明细篇)。

//我们上面3.1.1节提到的配置文件全路径
String resource = "org/mybatis/example/mybatis-config.xml";
//通过Mybatis提供的Resources工具类获取输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
//根据Mybatis提供的SqlSessionFactoryBuilder构建器构建用户定义的Configuration特有的SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

3.1.3.2、构建我们真正干活的SqlSession

//SqlSessionFactory 中获取 SqlSession
 SqlSession sqlSession = sqlSessionFactory.openSession()
 //执行上面我们3.1.2节提到的配置文件mapper中的方法,因为xml配置好的映射关系所以我们直接是通过sqlSession就可以拿到映射的mapper,怎么拿到的呢?依然是需要看下第二章中我提到的Mybatis核心设计图,通过动态代理的方式从Configuration对象中找到对应的mapper,method,parameter。所以从这里看Configuration就是整个一个仓库拥有所有你需要的东西。
  //从会话中获取绑定好的mapper接口信息
    AuthorMapperWithAnnotation mapper = sqlSession.getMapper(AuthorMapperWithAnnotation.class);
    //执行mapper接口的实现方法,而这段具体分析就到第四章和第五章可以学习源码,第三章主要将全局初始化这个过程。
    Author author = mapper.selectAuthorInfoById(101);

3.2、注解的配置解析示例

3.2.1、Mybatis-config.xml的使用示例

当然这里也可以使用properties文件属性等内容,或者springboot的yml文件等配置。

//1、xml的协议约束
<?xml version="1.0" encoding="UTF-8" ?>
//2、Configuration的协议约束
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
//3、全局配置类的约束
<configuration>
    //3.1、全局配置的属性和事务管理器
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="" value=""/>
            </transactionManager>
            <dataSource type="UNPOOLED">
                <property name="driver" value="org.hsqldb.jdbcDriver"/>
                <property name="url" value="jdbc:hsqldb:mem:automapping"/>
                <property name="username" value="sa"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

3.2.2、Mapper接口的使用示例

根据我们接口常用的CRUD操作这里分别提供了注解的实现方法形式。

public interface AuthorMapperWithAnnotation {
  //使用select注解直接查询
  @Select("select id, username, password, email, bio, favourite_section from author where id = #{id}")
  Author selectAuthorInfoById(int id);
 //使用SelectProvider注解直接查询
  @SelectProvider(type =AuthorProvider.class,method = "selectAuthorWithPlaceholder")
  Author selectAuthorWithPlaceholder(Author author);
//使用Insert注解直接查询
  @Insert("insert into author (id,username,password,email,bio) values (#{id},#{username},#{password},#{email},#{bio})")
  int insertAuthor(Author author);
//使用InsertProvider注解直接查询
  @InsertProvider(type =AuthorProvider.class,method = "insertAuthorWithPlaceholder")
  int insertAuthorWithPlaceholder(Author author);
//使用Update注解直接查询
  @Update("update author set username=#{username} where id =#{id}")
  int updateAuthor(Author author);
//使用UpdateProvider注解直接查询
  @UpdateProvider(type =AuthorProvider.class,method = "updateAuthorWithPlaceholder")
  void updateAuthorWithPlaceholder(Author author);
//使用Delete注解直接查询
  @Delete("delete from author where id = #{id}")
  int deleteAuthor(Author author);
//使用DeleteProvider注解直接查询
  @DeleteProvider(type =AuthorProvider.class,method = "deleteAuthorWithPlaceholder")
  int deleteAuthorWithPlaceholder(Author author);
//提供provider注解类的对应方法
   class AuthorProvider{
     //selectAuthorWithPlaceholder方法
     public String selectAuthorWithPlaceholder(Author author){
       return new SQL(){{
         SELECT("id,username,password,email,bio").FROM("author").WHERE("id=#{id}");
       }}.toString();
     }
     //insertAuthorWithPlaceholder方法
     public String insertAuthorWithPlaceholder(Author author){
       return new SQL(){{
         INSERT_INTO("Author").VALUES("id,username,password,email,bio","#{id},#{username},#{password},#{email},#{bio}");
       }}.toString();
     }
     //updateAuthorWithPlaceholder方法
     public String updateAuthorWithPlaceholder(Author author){
       return new SQL(){{
         UPDATE("Author").SET("id=#{id}","username=#{username}","password=#{password}","email=#{email}","bio=#{bio}").WHERE("id=#{id}");
       }}.toString();
     }
     //deleteAuthorWithPlaceholder方法
     public String deleteAuthorWithPlaceholder(Author author){
       return new SQL(){{
         DELETE_FROM("Author").WHERE("id=#{id}");
       }}.toString();
     }
  }
}

3.3.3、代码中注解的解析使用示例

//上述提到的输入流信息我们这里先以xml为例子
final String resource = "org/apache/ibatis/builder/Mybatis-config.xml";
final Reader reader = Resources.getResourceAsReader(resource);
//直接代码构建SqlSessionFactory
SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
//初始化全局配置---相当于Mybatis-config.xml中的绑定configuration标签
    Configuration configuration = new Configuration(sqlMapper.getConfiguration().getEnvironment());
//为全局配置添加需要的Mapper接口---相当于Mybatis-config.xml中的绑定Mapper.xml文件的标签
    configuration.addMapper(AuthorMapperWithAnnotation.class);
    //创建SQL会话工厂---利用SqlSessionFactory实现Bean实例化
    SqlSessionFactory sqlMapperWithAnnotation = new DefaultSqlSessionFactory(configuration);
    //获取SQL会话链接---所有Mybatis的核心API接口
    SqlSession sqlSession =  sqlMapperWithAnnotation.openSession();
    //从会话中获取绑定好的mapper接口信息---利用反射获取对应的mapper
    AuthorMapperWithAnnotation mapper = sqlSession.getMapper(AuthorMapperWithAnnotation.class);
    //执行插入会话---Mybatis核心设计图中动态代理执行过程(这里的源码分析可以参考第四章、第五章)
    Author expected = new Author(500, "wolf:\"test\"", "******", "liuxiaocheng@somewhere.com", "Something...", null);
    mapper.insertAuthorWithPlaceholder(expected);

3.3、核心类和核心方法

  • SqlSessionFactoryBuilder:SqlSessionFactory的构造器,可以自己解析配置,也可以通过提前构建好的配置对象构建。
  • SqlSessionFactory:管理数据库会话、聚合Configuration的属性。
  • Configuration:是全局所有的运行数据配置,相当于一个大的仓库。
  • XMLConfigBuilder:解析XML的Configuration构建器。
  • XMLMapperBuilder:解析XML的Mapper构建器。

根据时序图我们可以看到实际上分为三个过程【创建】-》【解析】-》【构建】

3.3.1、SqlSessionFactoryBuilder源码分析

public class SqlSessionFactoryBuilder {
  //根据字符流构建会话工厂
  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }
 ...省略本次无关内容...
  //根据字符流和环境和属性构建会话工厂
  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      //利用xml配置构建器
      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.
      }
    }
  }
   ...省略本次无关内容...
     
  //根据全局配置构建会话工厂,走默认的会话工厂
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

}

3.3.2、SqlSessionFactory源码分析

3.3.2.1、SqlSessionFactory源码分析

/*
 *从连接或数据源创建SqlSession
 */
public interface SqlSessionFactory {
  //打开会话
  SqlSession openSession();
  //打开会话是否自动提交
  SqlSession openSession(boolean autoCommit);
  //打开链接的session
  SqlSession openSession(Connection connection);
  //打开事务隔离级别的session
  SqlSession openSession(TransactionIsolationLevel level);
  //打开执行器类型的session
  SqlSession openSession(ExecutorType execType);
  //打开执行器类型,是否自动提交的session
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  //打开执行器和事务隔离级别机制的session
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  //打开执行器,链接的session
  SqlSession openSession(ExecutorType execType, Connection connection);
  //获取全局配置
  Configuration getConfiguration();

}

3.3.2.2、DefaultSqlSessionFactory源码分析


/**
 * 默认的会话工厂
 * @author Clinton Begin
 */
public class DefaultSqlSessionFactory implements SqlSessionFactory {
  //全局配置
  private final Configuration configuration;
  //构造函数
  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }
  
...省略本次无关内容...
}

3.3.3、Configuration源码分析


/**
 * 抽象构建器
 * @author Clinton Begin
 */
public abstract class BaseBuilder {
  //全局配置
  protected final Configuration configuration;
  //类型别名注册器
  protected final TypeAliasRegistry typeAliasRegistry;
  //类型处理器注册器
  protected final TypeHandlerRegistry typeHandlerRegistry;
  //构造函数
  public BaseBuilder(Configuration configuration) {
    this.configuration = configuration;
    this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
    this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
  }
  //获取全局配置
  public Configuration getConfiguration() {
    return configuration;
  }
  //解析正则表达式
  protected Pattern parseExpression(String regex, String defaultValue) {
    return Pattern.compile(regex == null ? defaultValue : regex);
  }
  //获取boolean值
  protected Boolean booleanValueOf(String value, Boolean defaultValue) {
    return value == null ? defaultValue : Boolean.valueOf(value);
  }
  //获取int值
  protected Integer integerValueOf(String value, Integer defaultValue) {
    return value == null ? defaultValue : Integer.valueOf(value);
  }
  //获取set值
  protected Set<String> stringSetValueOf(String value, String defaultValue) {
    value = value == null ? defaultValue : value;
    return new HashSet<>(Arrays.asList(value.split(",")));
  }
  //解析jdbc类型
  protected JdbcType resolveJdbcType(String alias) {
    if (alias == null) {
      return null;
    }
    try {
      return JdbcType.valueOf(alias);
    } catch (IllegalArgumentException e) {
      throw new BuilderException("Error resolving JdbcType. Cause: " + e, e);
    }
  }
  //解析结果集类型
  protected ResultSetType resolveResultSetType(String alias) {
    if (alias == null) {
      return null;
    }
    try {
      return ResultSetType.valueOf(alias);
    } catch (IllegalArgumentException e) {
      throw new BuilderException("Error resolving ResultSetType. Cause: " + e, e);
    }
  }
  //解析参数风格
  protected ParameterMode resolveParameterMode(String alias) {
    if (alias == null) {
      return null;
    }
    try {
      return ParameterMode.valueOf(alias);
    } catch (IllegalArgumentException e) {
      throw new BuilderException("Error resolving ParameterMode. Cause: " + e, e);
    }
  }
  //创建实例
  protected Object createInstance(String alias) {
    Class<?> clazz = resolveClass(alias);
    if (clazz == null) {
      return null;
    }
    try {
      return clazz.getDeclaredConstructor().newInstance();
    } catch (Exception e) {
      throw new BuilderException("Error creating instance. Cause: " + e, e);
    }
  }
  //根据别名解析类
  protected <T> Class<? extends T> resolveClass(String alias) {
    if (alias == null) {
      return null;
    }
    try {
      return resolveAlias(alias);
    } catch (Exception e) {
      throw new BuilderException("Error resolving class. Cause: " + e, e);
    }
  }
  //解析类型处理器
  protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, String typeHandlerAlias) {
    if (typeHandlerAlias == null) {
      return null;
    }
    Class<?> type = resolveClass(typeHandlerAlias);
    if (type != null && !TypeHandler.class.isAssignableFrom(type)) {
      throw new BuilderException("Type " + type.getName() + " is not a valid TypeHandler because it does not implement TypeHandler interface");
    }
    @SuppressWarnings("unchecked") // already verified it is a TypeHandler
    Class<? extends TypeHandler<?>> typeHandlerType = (Class<? extends TypeHandler<?>>) type;
    return resolveTypeHandler(javaType, typeHandlerType);
  }
  //解析类型处理器
  protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, Class<? extends TypeHandler<?>> typeHandlerType) {
    if (typeHandlerType == null) {
      return null;
    }
    // javaType ignored for injected handlers see issue #746 for full detail
    TypeHandler<?> handler = typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);
    if (handler == null) {
      // not in registry, create a new one
      handler = typeHandlerRegistry.getInstance(javaType, typeHandlerType);
    }
    return handler;
  }
  //解析别名
  protected <T> Class<? extends T> resolveAlias(String alias) {
    return typeAliasRegistry.resolveAlias(alias);
  }
}

3.3.4.1、XMLConfigBuilder源码分析

/**
 * xml配置构建器
 * @author Clinton Begin
 * @author Kazuki Shimizu
 */
public class XMLConfigBuilder extends BaseBuilder {
  //是否解析
  private boolean parsed;
  //解析器
  private final XPathParser parser;
  //环境
  private String environment;
  //本地反射工厂
  private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
  //构造函数
  public XMLConfigBuilder(Reader reader) {
    this(reader, null, null);
  }
  //构造函数
  public XMLConfigBuilder(Reader reader, String environment) {
    this(reader, environment, null);
  }
  //构造函数
  public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
  }
  //构造函数
  public XMLConfigBuilder(InputStream inputStream) {
    this(inputStream, null, null);
  }
  //构造函数
  public XMLConfigBuilder(InputStream inputStream, String environment) {
    this(inputStream, environment, null);
  }
   //构造函数
  public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
    this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
  }
   //私有构造函数
  private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    super(new Configuration());
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
  }
  //解析全局配置对象
  public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }
   //解析全局配置对象
  private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      //解析属性变量节点
      propertiesElement(root.evalNode("properties"));
      //解析setting节点字段
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      //加载用户自定义的VFS解析文件类
      loadCustomVfs(settings);
      //加载用户自定义的日志实现
      loadCustomLogImpl(settings);
      //类型别名元素绑定
      typeAliasesElement(root.evalNode("typeAliases"));
      //插件元素
      pluginElement(root.evalNode("plugins"));
      //对象工厂元素
      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"));
      //数据库ID
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      //类型处理器元素
      typeHandlerElement(root.evalNode("typeHandlers"));
      //mapper接口元素
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }
  //设置属性
  private Properties settingsAsProperties(XNode context) {
    if (context == null) {
      return new Properties();
    }
    Properties props = context.getChildrenAsProperties();
    //检查所有的setting设置是在配置类中已知的
    // Check that all settings are known to the configuration class
    MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
    for (Object key : props.keySet()) {
      if (!metaConfig.hasSetter(String.valueOf(key))) {
        throw new BuilderException("The setting " + key + " is not known.  Make sure you spelled it correctly (case sensitive).");
      }
    }
    return props;
  }
   //加载定制vfs解析实现类
  private void loadCustomVfs(Properties props) throws ClassNotFoundException {
    String value = props.getProperty("vfsImpl");
    if (value != null) {
      String[] clazzes = value.split(",");
      for (String clazz : clazzes) {
        if (!clazz.isEmpty()) {
          @SuppressWarnings("unchecked")
          Class<? extends VFS> vfsImpl = (Class<? extends VFS>)Resources.classForName(clazz);
          configuration.setVfsImpl(vfsImpl);
        }
      }
    }
  }
  //加载定制实现类
  private void loadCustomLogImpl(Properties props) {
    Class<? extends Log> logImpl = resolveClass(props.getProperty("logImpl"));
    configuration.setLogImpl(logImpl);
  }
  //类型别名元素
  private void typeAliasesElement(XNode parent) {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String typeAliasPackage = child.getStringAttribute("name");
          configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
        } else {
          String alias = child.getStringAttribute("alias");
          String type = child.getStringAttribute("type");
          try {
            Class<?> clazz = Resources.classForName(type);
            if (alias == null) {
              typeAliasRegistry.registerAlias(clazz);
            } else {
              typeAliasRegistry.registerAlias(alias, clazz);
            }
          } catch (ClassNotFoundException e) {
            throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
          }
        }
      }
    }
  }
 //插件元素
  private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String interceptor = child.getStringAttribute("interceptor");
        Properties properties = child.getChildrenAsProperties();
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
        interceptorInstance.setProperties(properties);
        configuration.addInterceptor(interceptorInstance);
      }
    }
  }
  //对象工厂元素
  private void objectFactoryElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties properties = context.getChildrenAsProperties();
      ObjectFactory factory = (ObjectFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      factory.setProperties(properties);
      configuration.setObjectFactory(factory);
    }
  }
  //对象包装工厂元素
  private void objectWrapperFactoryElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      ObjectWrapperFactory factory = (ObjectWrapperFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      configuration.setObjectWrapperFactory(factory);
    }
  }
  //反射工厂元素
  private void reflectorFactoryElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      ReflectorFactory factory = (ReflectorFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      configuration.setReflectorFactory(factory);
    }
  }
//属性元素
  private void propertiesElement(XNode context) throws Exception {
    if (context != null) {
      Properties defaults = context.getChildrenAsProperties();
      String resource = context.getStringAttribute("resource");
      String url = context.getStringAttribute("url");
      if (resource != null && url != null) {
        throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.");
      }
      if (resource != null) {
        defaults.putAll(Resources.getResourceAsProperties(resource));
      } else if (url != null) {
        defaults.putAll(Resources.getUrlAsProperties(url));
      }
      Properties vars = configuration.getVariables();
      if (vars != null) {
        defaults.putAll(vars);
      }
      parser.setVariables(defaults);
      configuration.setVariables(defaults);
    }
  }
  //设置属性
  private void settingsElement(Properties props) {
    configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
    configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
    configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
    configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
    configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
    configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
    configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
    configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
    configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
    configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
    configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
    configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
    configuration.setDefaultResultSetType(resolveResultSetType(props.getProperty("defaultResultSetType")));
    configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
    configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
    configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
    configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
    configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
    configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
    configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
    configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
    configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
    configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
    configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
    configuration.setLogPrefix(props.getProperty("logPrefix"));
    configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
  }
  //环境元素
  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          DataSource dataSource = dsFactory.getDataSource();
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }
  //数据库ID服务元素
  private void databaseIdProviderElement(XNode context) throws Exception {
    DatabaseIdProvider databaseIdProvider = null;
    if (context != null) {
      String type = context.getStringAttribute("type");
      // awful patch to keep backward compatibility
      if ("VENDOR".equals(type)) {
        type = "DB_VENDOR";
      }
      Properties properties = context.getChildrenAsProperties();
      databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance();
      databaseIdProvider.setProperties(properties);
    }
    Environment environment = configuration.getEnvironment();
    if (environment != null && databaseIdProvider != null) {
      String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
      configuration.setDatabaseId(databaseId);
    }
  }
  //事务处理的元素
  private TransactionFactory transactionManagerElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      TransactionFactory factory = (TransactionFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a TransactionFactory.");
  }
  //数据源处理的元素
  private DataSourceFactory dataSourceElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a DataSourceFactory.");
  }
  //类型处理器的元素
  private void typeHandlerElement(XNode parent) {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String typeHandlerPackage = child.getStringAttribute("name");
          typeHandlerRegistry.register(typeHandlerPackage);
        } else {
          String javaTypeName = child.getStringAttribute("javaType");
          String jdbcTypeName = child.getStringAttribute("jdbcType");
          String handlerTypeName = child.getStringAttribute("handler");
          Class<?> javaTypeClass = resolveClass(javaTypeName);
          JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
          Class<?> typeHandlerClass = resolveClass(handlerTypeName);
          if (javaTypeClass != null) {
            if (jdbcType == null) {
              typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
            } else {
              typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
            }
          } else {
            typeHandlerRegistry.register(typeHandlerClass);
          }
        }
      }
    }
  }
  //mapper文件解析元素
  private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }
  //是否指定环境
  private boolean isSpecifiedEnvironment(String id) {
    if (environment == null) {
      throw new BuilderException("No environment specified.");
    } else if (id == null) {
      throw new BuilderException("Environment requires an id attribute.");
    } else if (environment.equals(id)) {
      return true;
    }
    return false;
  }

}

3.3.4.2、XMLMapperBuilder源码分析

/**
 * XML的mapper接口构建器
 */
public class XMLMapperBuilder extends BaseBuilder {
  //解析器
  private final XPathParser parser;
  //接口助手
  private final MapperBuilderAssistant builderAssistant;
  //sql节点片段
  private final Map<String, XNode> sqlFragments;
  //资源
  private final String resource;
  //不建议使用,未来废弃
  @Deprecated
  public XMLMapperBuilder(Reader reader, Configuration configuration, String resource, Map<String, XNode> sqlFragments, String namespace) {
    this(reader, configuration, resource, sqlFragments);
    this.builderAssistant.setCurrentNamespace(namespace);
  }
  //不建议使用,未来废弃
  @Deprecated
  public XMLMapperBuilder(Reader reader, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
    this(new XPathParser(reader, true, configuration.getVariables(), new XMLMapperEntityResolver()),
        configuration, resource, sqlFragments);
  }
  //构造函数
  public XMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource, Map<String, XNode> sqlFragments, String namespace) {
    this(inputStream, configuration, resource, sqlFragments);
    this.builderAssistant.setCurrentNamespace(namespace);
  }
  //构造函数
  public XMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
    this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()),
        configuration, resource, sqlFragments);
  }
   //构造函数
  private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
    super(configuration);
    this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
    this.parser = parser;
    this.sqlFragments = sqlFragments;
    this.resource = resource;
  }
  //解析mapper
  public void parse() {
    if (!configuration.isResourceLoaded(resource)) {
      configurationElement(parser.evalNode("/mapper"));
      configuration.addLoadedResource(resource);
      //将mapper和命名空间绑定
      bindMapperForNamespace();
    }
    //解析等待的结果映射
    parsePendingResultMaps();
    //解析等待的缓存引用
    parsePendingCacheRefs();
    //解析等待的会话
    parsePendingStatements();
  }
  //获取sql片段根据引用ID
  public XNode getSqlFragment(String refid) {
    return sqlFragments.get(refid);
  }
  //配置全局配置
  private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      //绑定当前的命名空间
      builderAssistant.setCurrentNamespace(namespace);
      //缓存引用
      cacheRefElement(context.evalNode("cache-ref"));
      //缓存
      cacheElement(context.evalNode("cache"));
      //参数map
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      //结果map
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      //sql
      sqlElement(context.evalNodes("/mapper/sql"));
      //会话语句
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }
  //构建会话从上下文
  private void buildStatementFromContext(List<XNode> list) {
    if (configuration.getDatabaseId() != null) {
      buildStatementFromContext(list, configuration.getDatabaseId());
    }
    buildStatementFromContext(list, null);
  }
  //构建会话从上下文
  private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
    for (XNode context : list) {
      final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
      try {
        statementParser.parseStatementNode();
      } catch (IncompleteElementException e) {
        configuration.addIncompleteStatement(statementParser);
      }
    }
  }
  //解析等待的结果映射
  private void parsePendingResultMaps() {
    Collection<ResultMapResolver> incompleteResultMaps = configuration.getIncompleteResultMaps();
    synchronized (incompleteResultMaps) {
      Iterator<ResultMapResolver> iter = incompleteResultMaps.iterator();
      while (iter.hasNext()) {
        try {
          iter.next().resolve();
          iter.remove();
        } catch (IncompleteElementException e) {
          // ResultMap is still missing a resource...
        }
      }
    }
  }
  //解析等待的缓存引用
  private void parsePendingCacheRefs() {
    Collection<CacheRefResolver> incompleteCacheRefs = configuration.getIncompleteCacheRefs();
    synchronized (incompleteCacheRefs) {
      Iterator<CacheRefResolver> iter = incompleteCacheRefs.iterator();
      while (iter.hasNext()) {
        try {
          iter.next().resolveCacheRef();
          iter.remove();
        } catch (IncompleteElementException e) {
          // Cache ref is still missing a resource...
        }
      }
    }
  }
  //解析等待的会话
  private void parsePendingStatements() {
    Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();
    synchronized (incompleteStatements) {
      Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();
      while (iter.hasNext()) {
        try {
          iter.next().parseStatementNode();
          iter.remove();
        } catch (IncompleteElementException e) {
          // Statement is still missing a resource...
        }
      }
    }
  }
  //缓存引用元素
  private void cacheRefElement(XNode context) {
    if (context != null) {
      configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
      CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
      try {
        cacheRefResolver.resolveCacheRef();
      } catch (IncompleteElementException e) {
        configuration.addIncompleteCacheRef(cacheRefResolver);
      }
    }
  }
  //缓存元素
  private void cacheElement(XNode context) {
    if (context != null) {
      String type = context.getStringAttribute("type", "PERPETUAL");
      Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
      String eviction = context.getStringAttribute("eviction", "LRU");
      Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
      Long flushInterval = context.getLongAttribute("flushInterval");
      Integer size = context.getIntAttribute("size");
      boolean readWrite = !context.getBooleanAttribute("readOnly", false);
      boolean blocking = context.getBooleanAttribute("blocking", false);
      Properties props = context.getChildrenAsProperties();
      builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
    }
  }
  //参数映射元素
  private void parameterMapElement(List<XNode> list) {
    for (XNode parameterMapNode : list) {
      String id = parameterMapNode.getStringAttribute("id");
      String type = parameterMapNode.getStringAttribute("type");
      Class<?> parameterClass = resolveClass(type);
      List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
      List<ParameterMapping> parameterMappings = new ArrayList<>();
      for (XNode parameterNode : parameterNodes) {
        String property = parameterNode.getStringAttribute("property");
        String javaType = parameterNode.getStringAttribute("javaType");
        String jdbcType = parameterNode.getStringAttribute("jdbcType");
        String resultMap = parameterNode.getStringAttribute("resultMap");
        String mode = parameterNode.getStringAttribute("mode");
        String typeHandler = parameterNode.getStringAttribute("typeHandler");
        Integer numericScale = parameterNode.getIntAttribute("numericScale");
        ParameterMode modeEnum = resolveParameterMode(mode);
        Class<?> javaTypeClass = resolveClass(javaType);
        JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
        Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
        ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
        parameterMappings.add(parameterMapping);
      }
      builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
    }
  }
  //结果映射
  private void resultMapElements(List<XNode> list) throws Exception {
    for (XNode resultMapNode : list) {
      try {
        resultMapElement(resultMapNode);
      } catch (IncompleteElementException e) {
        // ignore, it will be retried
      }
    }
  }
  //结果映射
  private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
    return resultMapElement(resultMapNode, Collections.emptyList(), null);
  }
  //结果映射
  private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) throws Exception {
    ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
    String type = resultMapNode.getStringAttribute("type",
        resultMapNode.getStringAttribute("ofType",
            resultMapNode.getStringAttribute("resultType",
                resultMapNode.getStringAttribute("javaType"))));
    Class<?> typeClass = resolveClass(type);
    if (typeClass == null) {
      typeClass = inheritEnclosingType(resultMapNode, enclosingType);
    }
    Discriminator discriminator = null;
    List<ResultMapping> resultMappings = new ArrayList<>();
    resultMappings.addAll(additionalResultMappings);
    List<XNode> resultChildren = resultMapNode.getChildren();
    for (XNode resultChild : resultChildren) {
      if ("constructor".equals(resultChild.getName())) {
        processConstructorElement(resultChild, typeClass, resultMappings);
      } else if ("discriminator".equals(resultChild.getName())) {
        discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
      } else {
        List<ResultFlag> flags = new ArrayList<>();
        if ("id".equals(resultChild.getName())) {
          flags.add(ResultFlag.ID);
        }
        resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
      }
    }
    String id = resultMapNode.getStringAttribute("id",
            resultMapNode.getValueBasedIdentifier());
    String extend = resultMapNode.getStringAttribute("extends");
    Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
    ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
    try {
      return resultMapResolver.resolve();
    } catch (IncompleteElementException  e) {
      configuration.addIncompleteResultMap(resultMapResolver);
      throw e;
    }
  }
  //继承封装类型
  protected Class<?> inheritEnclosingType(XNode resultMapNode, Class<?> enclosingType) {
    if ("association".equals(resultMapNode.getName()) && resultMapNode.getStringAttribute("resultMap") == null) {
      String property = resultMapNode.getStringAttribute("property");
      if (property != null && enclosingType != null) {
        MetaClass metaResultType = MetaClass.forClass(enclosingType, configuration.getReflectorFactory());
        return metaResultType.getSetterType(property);
      }
    } else if ("case".equals(resultMapNode.getName()) && resultMapNode.getStringAttribute("resultMap") == null) {
      return enclosingType;
    }
    return null;
  }
  //执行构造元素
  private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
    List<XNode> argChildren = resultChild.getChildren();
    for (XNode argChild : argChildren) {
      List<ResultFlag> flags = new ArrayList<>();
      flags.add(ResultFlag.CONSTRUCTOR);
      if ("idArg".equals(argChild.getName())) {
        flags.add(ResultFlag.ID);
      }
      resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
    }
  }
  //执行鉴别器元素
  private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
    String column = context.getStringAttribute("column");
    String javaType = context.getStringAttribute("javaType");
    String jdbcType = context.getStringAttribute("jdbcType");
    String typeHandler = context.getStringAttribute("typeHandler");
    Class<?> javaTypeClass = resolveClass(javaType);
    Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
    JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
    Map<String, String> discriminatorMap = new HashMap<>();
    for (XNode caseChild : context.getChildren()) {
      String value = caseChild.getStringAttribute("value");
      String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings, resultType));
      discriminatorMap.put(value, resultMap);
    }
    return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap);
  }
  //sql元素
  private void sqlElement(List<XNode> list) {
    if (configuration.getDatabaseId() != null) {
      sqlElement(list, configuration.getDatabaseId());
    }
    sqlElement(list, null);
  }
  //sql元素
  private void sqlElement(List<XNode> list, String requiredDatabaseId) {
    for (XNode context : list) {
      String databaseId = context.getStringAttribute("databaseId");
      String id = context.getStringAttribute("id");
      id = builderAssistant.applyCurrentNamespace(id, false);
      if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
        sqlFragments.put(id, context);
      }
    }
  }
  //数据库ID匹配当前要求
  private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {
    if (requiredDatabaseId != null) {
      return requiredDatabaseId.equals(databaseId);
    }
    if (databaseId != null) {
      return false;
    }
    if (!this.sqlFragments.containsKey(id)) {
      return true;
    }
    // skip this fragment if there is a previous one with a not null databaseId
    XNode context = this.sqlFragments.get(id);
    return context.getStringAttribute("databaseId") == null;
  }
  //从上下文构建结果映射
  private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception {
    String property;
    if (flags.contains(ResultFlag.CONSTRUCTOR)) {
      property = context.getStringAttribute("name");
    } else {
      property = context.getStringAttribute("property");
    }
    String column = context.getStringAttribute("column");
    String javaType = context.getStringAttribute("javaType");
    String jdbcType = context.getStringAttribute("jdbcType");
    String nestedSelect = context.getStringAttribute("select");
    String nestedResultMap = context.getStringAttribute("resultMap",
        processNestedResultMappings(context, Collections.emptyList(), resultType));
    String notNullColumn = context.getStringAttribute("notNullColumn");
    String columnPrefix = context.getStringAttribute("columnPrefix");
    String typeHandler = context.getStringAttribute("typeHandler");
    String resultSet = context.getStringAttribute("resultSet");
    String foreignColumn = context.getStringAttribute("foreignColumn");
    boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
    Class<?> javaTypeClass = resolveClass(javaType);
    Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
    JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
    return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy);
  }
  //执行嵌套结果映射
  private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings, Class<?> enclosingType) throws Exception {
    if ("association".equals(context.getName())
        || "collection".equals(context.getName())
        || "case".equals(context.getName())) {
      if (context.getStringAttribute("select") == null) {
        validateCollection(context, enclosingType);
        ResultMap resultMap = resultMapElement(context, resultMappings, enclosingType);
        return resultMap.getId();
      }
    }
    return null;
  }
  //校验集合
  protected void validateCollection(XNode context, Class<?> enclosingType) {
    if ("collection".equals(context.getName()) && context.getStringAttribute("resultMap") == null
        && context.getStringAttribute("javaType") == null) {
      MetaClass metaResultType = MetaClass.forClass(enclosingType, configuration.getReflectorFactory());
      String property = context.getStringAttribute("property");
      if (!metaResultType.hasSetter(property)) {
        throw new BuilderException(
          "Ambiguous collection type for property '" + property + "'. You must specify 'javaType' or 'resultMap'.");
      }
    }
  }
  //构建命名空间的mapper
  private void bindMapperForNamespace() {
    String namespace = builderAssistant.getCurrentNamespace();
    if (namespace != null) {
      Class<?> boundType = null;
      try {
        boundType = Resources.classForName(namespace);
      } catch (ClassNotFoundException e) {
        //ignore, bound type is not required
      }
      if (boundType != null) {
        if (!configuration.hasMapper(boundType)) {
         
          configuration.addLoadedResource("namespace:" + namespace);
          configuration.addMapper(boundType);
        }
      }
    }
  }

}

Mybatis构建加载初始化源码分析这节到这里就结束了,可以再回顾下核心重点图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小诚信驿站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值