In-depth analysis of the running process of mybatis (1)

The operation of mybatis is divided into two steps:

1. Read the configuration file and cache it in the Configuration object to create the SQLSessionFactory;

2. The execution process of SQLSession.

First let's talk about this SQLSessionFactory construction;

First of all, we need to know that SQLSessionFactory is an interface, not an implementation class. Mybatis provides him with a default implementation class org.apache.ibatis.session.defaults.DefaultSqlSessionFactory. From the source code we can also see:

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

When creating SQLSessionFactory, it is handed over to DefaultSqlSessionFactory for execution; at the same time, here, we find the most important Configuration object when creating SQLSessionFactory; then let's look at:

  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.
      }
    }
  }

This method is the method that calls the method just now, we can find the return build(parser.parse()); called here; then continue to go up, we see the XMLConfigBuilder class, which inherits the BaseBuilder class; now we can Know that the Configuration object is created by XMLConfigBuilder. So how did he create it? Then continue to follow up:

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

We found the parse() method in the XMLConfigBuilder class, and then we looked at parseConfiguration(parser.evalNode("/configuration")); how this method is implemented:

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);
    }
  }

At first glance, I feel a lot, but in fact, these are just doing the same job, parsing the information corresponding to xml;

propertiesElement(root.evalNode("properties"));//Properties file, database driven configuration?
 typeAliasesElement(root.evalNode("typeAliases"));//Type dialect for result conversion
 pluginElement(root.evalNode("plugins"));//Plugins, you can configure interceptors at different times
 objectFactoryElement(root.evalNode("objectFactory"));//Object factory, you can configure the returned object properties
 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
 settingsElement(root.evalNode("settings")); //Configuration of global variables, cache, lazy loading, etc.
 environmentsElement(root.evalNode("environments")); //Environment variables, build data source factories and transaction factories according to the configuration
 databaseIdProviderElement(root.evalNode("databaseIdProvider"));//The database provides an ID, which is used when multiple databases are compatible
 typeHandlerElement(root.evalNode("typeHandlers")); //Type handler, mainly for result set, type conversion processing
 mapperElement(root.evalNode("mappers"));//Different mapper dao processing

Here we know the whole process, but let me say more here, that is typeHandler, because this parsing process is very important;

We continue to follow up the typeHandlerElement(root.evalNode("typeHandlers")); method:

  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);
          }
        }
      }
    }

From the source code, we can see that he was registered in the typeHandlerRegistry object, but how did this object come from, it is not defined in XMLConfigBuilder, it can only come from the parent class BaseBuilder of XMLConfigBuilder, which is from it, we Follow up and take a look,

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(); Through this code, we can get: the original typeHandlerRegistry object is actually an attribute of Configuration simple interest, so we can get the typeHandlerRegistry object through Configuration simple interest, and then we get all the registered typeHandler;







Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325592240&siteId=291194637