mybatis运行过程深度解析(一)

mybatis的运行分为两大步:

1.读取配置文件缓存到Configuration对象中,用以创建SQLSessionFactory;

2.SQLSession的执行过程。

首先我们来说一下这个SQLSessionFactory构建;

首先我们要知道,SQLSessionFactory是一个接口,而不是一个实现类,mybatis给他提供了一个默认的实现类org.apache.ibatis.session.defaults.DefaultSqlSessionFactory。从源码中我们也能够看出:

  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

创建SQLSessionFactory的时候,是交给DefaultSqlSessionFactory去执行的;同时在这里,我们发现在创建SQLSessionFactory时,最重要的Configuration对象;那我们接着看:

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      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.
      }
    }
  }

这个方法是调用刚才那个方法的方法,我们能够找到 return build(parser.parse());在这里调用的;然后继续往上走,我们看到了XMLConfigBuilder这个类,他继承了BaseBuilder的类;现在能够知道了Configuration对象是由XMLConfigBuilder创建的了吧。那他是怎么创建的呢?接着继续跟进:

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

我们到XMLConfigBuilder类中找到了parse()方法,然后我们接着看parseConfiguration(parser.evalNode("/configuration"));这个方法是怎么实现的:

private void parseConfiguration(XNode root) {
    try {
      Properties settings = settingsAsPropertiess(root.evalNode("settings"));
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      loadCustomVfs(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"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

打眼一看感觉不少,其实这些只是做了一样工作,解析xml对应的信息;

 propertiesElement(root.evalNode("properties"));//属性文件,数据库驱动配置?
 typeAliasesElement(root.evalNode("typeAliases"));//类型方言,用于结果转换 
 pluginElement(root.evalNode("plugins"));//插件,可以配置不同时机的拦截器
 objectFactoryElement(root.evalNode("objectFactory"));//对象工厂,可以配置返回对象属性
 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
 settingsElement(root.evalNode("settings")); //全局变量,缓存,延迟加载等配置
 environmentsElement(root.evalNode("environments")); //环境变量,根据配置构建数据源工厂,事务工厂
 databaseIdProviderElement(root.evalNode("databaseIdProvider"));//数据库提供标识ID,多数据库兼容的时候用到
 typeHandlerElement(root.evalNode("typeHandlers"));  //类型处理器,主要是对结果集,类型转换处理
 mapperElement(root.evalNode("mappers"));//不同的mapper  dao处理

到这里我们就知道整个流程了,但是在这多说一下,那就是typeHandler,因为这个解析过程很重要;

我们继续跟进typeHandlerElement(root.evalNode("typeHandlers"));方法:

  private void typeHandlerElement(XNode parent) throws Exception {
    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);
          }
        }
      }
    }

从源码中,我们看出,他被注册到了typeHandlerRegistry对象中去了,但这个对象怎么来的,XMLConfigBuilder中并没有定义它,那就只能是来自XMLConfigBuilder的父类BaseBuilder了,就是来自它,我们跟进看一下,

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();
  }
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();通过这句代码,我们能获得:原来typeHandlerRegistry对象实际就是Configuration单利的一个属性,所以我们可以通过Configuration单利拿到typeHandlerRegistry对象,进而我们拿到所注册的typeHandler;







猜你喜欢

转载自blog.csdn.net/hbl6016/article/details/80153317