编程知识 cdmana.com

Back end technology: how does mybatis parse configuration files?

Focus on “Java Back end technology stack ”

reply “ interview ” Get a full set of interview materials

In previous articles , We put Mybatis The whole process of reading the source code is sorted out . today , Let's talk about it in detail ,Mybatis How to parse the configuration file .

This is the flow chart of today's analysis :

Or start with the case .

demo Case study

   public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            sqlSession = sqlSessionFactory.openSession();

            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            System.out.println(userMapper.selectById(1));

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            sqlSession.close();
        }
    }

Witness the miracle

from SqlSessionFactoryBuilder Start .

SqlSessionFactoryBuilder class

org.apache.ibatis.session.SqlSessionFactoryBuilder

It's all in this category build Methods various overloads .



// This method did nothing   
public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, nullnull);
 }

And finally came to another build In the method :

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      // Create a XMLConfigBuilder object   
      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.
      }
    }
  }

XMLConfigBuilder class

The constructor of this class overloads :

First of all to enter :

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

build(parser.parse()); Medium parser.parse();

mybatis-config.xml Where did it come from ?

Take a look at the following method :

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

parseConfiguration(parser.evalNode("/configuration"));

Finally, it's time to start parsing the configuration file :

How to get in parseConfiguration.

  private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      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"));
      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);
    }
  }

Here is the mybatis-config.xml Content analysis , Then set it to Configuration In the object .

So we define Mapper.xml Where did it come from ?

our Mapper.xml stay mybatis-config.xml This is the configuration in :

<mapper> There are four ways to use it :

//1 Using Classpaths 
<mappers>
    <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
   <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
//2 Use absolute url route 
<mappers>
   <mapper url="file:///var/mappers/AuthorMapper.xml"/>
   <mapper url="file:///var/mappers/BlogMapper.xml"/>
   <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
//3 Use java Class name 
<mappers>
   <mapper class="org.mybatis.builder.AuthorMapper"/>
   <mapper class="org.mybatis.builder.BlogMapper"/>
   <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

//4 Automatically scan all mappers under the package 
<mappers>
   <package name="org.mybatis.builder"/>
</mappers>

Continue source code analysis , We're on it mybatis-config.xml We can see from the analysis that :

Let's go into this method and see :

 private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        // Automatically scan all mappers under the package 
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          // discharge   
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          // Use java Class name 
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
             // According to the file storage directory , Read XxxMapper.xml
            InputStream inputStream = Resources.getResourceAsStream(resource);
             // Mapper is more complex , call XMLMapperBuilder
            // Pay attention to for Every one in the loop mapper All over again new One XMLMapperBuilder, Parsing 
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          // Use absolute url route 
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            // Mapper is more complex , call XMLMapperBuilder
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          // Using Classpaths     
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            // Add this mapping directly to the configuration 
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }

Here and what we said above <mapper> The way of using as like as two peas .

Come here , The configuration file mybatis-config.xml And we define the mapping file XxxMapper.xml All the parsing is done .

go back to SqlSessionFactoryBuilder class

We talked about XMLConfigBuilder Medium parse Method , And back to a Configuration object .

build(parser.parse());

This build The method is to pass in a Configuration object , Then build a DefaultSqlSession object .

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

Go back to our demo In this line of code :

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

This line of code is equivalent to :

SqlSessionFactory sqlSessionFactory = new new DefaultSqlSessionFactory();

Come here , Our whole process is finished .

IT Technology sharing community

Personal blog site :https://programmerblog.xyz

Article recommendation Programmer efficiency : Common tools for drawing flowcharts Programmer efficiency : Organize common online note taking software Telecommuting : Commonly used remote assistance software , Do you know ?51 MCU download program 、ISP And basic knowledge of serial port Hardware : Circuit breaker 、 Contactor 、 Basic knowledge of relay

版权声明
本文为[osc_ 3r4js8qy]所创,转载请带上原文链接,感谢
https://cdmana.com/2020/12/20201225130401788h.html

Scroll to Top