Análisis inicial del código fuente de Mybatis (1)

La guía del código fuente de mybatis que ha estado de lado durante mucho tiempo, hoy daré un pequeño resumen.
¿Leer el código fuente? Creo que debería hacerse en orden de macro a micro. Si es necesario, incluso puedes agregar tu propio proceso gráfico para aclarar tus ideas.

Primeros pensamientos sobre mybatis

  1. En primer lugar, mybatis es un marco para simplificar operaciones.
  2. Entonces su existencia reemplaza la conexión jdbc, por lo que debe incluir las operaciones básicas de conexión a la base de datos.

Sobre el funcionamiento de jdbc

package jdbc;

import java.sql.*;
/**
 * @Author:XK
 * @Date: Created in 17:48 2021/10/26
 * @Description:jdbc的简单实现
 **/
public class jdbcFirstDemo {
    
    
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    
    
        //1加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2用户信息和URL
        String url ="jdbc:mysql://localhost:3306/fisrt21?useUnicod=true&characterEncoding=utf8&useSSL=true";
        String username="root";
        String password = "2020";

        //3连接成功 获取到数据库对象,Connection
        Connection connection = DriverManager.getConnection(url,username,password);

        //4.执行sql对象statement 执行sql的对象
        Statement statement = connection.createStatement();

        // 5 . 执行sql对象之后返回的结果集 Resultset
        String sql ="select * from class";

        ResultSet resultSet= statement.executeQuery(sql);

        while (resultSet.next()){
    
    
            System.out.println(resultSet.getString("class_name"));
        }

        //6 释放连接
        resultSet.close();
        statement.close();
        connection.close();

    }
}

Creo que hay tres partes: fuente de datos, declaración SQL y operación de datos.

  • La fuente de datos aquí es una configuración que incluye URL, nombre de usuario y contraseña. Puede conectarse a la base de datos a través de este
  • La declaración SQL es una declaración SQL que escribí manualmente.
  • La operación de datos es el proceso en el que el objeto de mi base de datos de conexión obtiene la declaración del objeto SQL y luego ejecuta la declaración SQL a través de la declaración para obtener un conjunto de resultados.
    Esta es una operación de conexión de base de datos jdbc que creo que es muy básica.

Dado que el marco mybats reemplaza la conexión jdbc, también debe completar estas tres tareas y el orden es similar: es necesario verificar si es correcto o no en el código fuente. Luego tomé esta pregunta y entré a leer el código fuente.

Primera lectura del código fuente de mabatis

No sé cómo otros leen un código fuente. Para mí, simplemente escribo una demostración y luego paso por el proceso de depuración de la idea para ver paso a paso cómo es este marco. A través del documento oficial de mybatis, Documento
oficial de mybatis y extraiga el código fuente de mybatis de GitHub.

package test1;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import javax.sound.sampled.Line;
import java.io.IOException;
import java.io.InputStream;


/**
 * @Author:XK
 * @Date: Created in 16:25 2022/4/3
 * @Description:
 **/
public class demo {
    
    
  public static void main(String[] args) throws IOException {
    
    
    String resource = "resources/mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    sqlSession.getMapper(UsrMapper.class).selectAll();
  }
}

Escriba una demostración tan pequeña para comenzar a analizar.
En primer lugar, comenzando desde la primera línea de código, convierta la configuración de config.xml en inputstream y luego ejecute la compilación de un método sqlsessionFactory. Cualquiera que esté familiarizado con
mybatis sabe que cada aplicación basada en MyBatis se centra en una instancia de SqlSessionFactory. Se pueden obtener instancias de SqlSessionFactory a través de SqlSessionFactoryBuilder. SqlSessionFactoryBuilder puede crear una instancia de SqlSessionFactory a partir de un archivo de configuración XML o una instancia de configuración preconfigurada.
Este paso consiste en construir una instancia de SqlSessionFactory mediante el análisis de config.xml, y es única.

Veamos qué se construye exactamente en el método de compilación.

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

Obviamente hay una clase XMLConfigBuilder. Por el nombre de la clase, puedo adivinar aproximadamente para qué sirve. Probablemente sea una clase de herramienta utilizada para analizar archivos xml. Obviamente, se ejecuta un método XMLConfigBuilder.parse() antes de compilar. Clic para ver

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

Se llama al método parseConfiguration para analizar la configuración.
Mire algunos métodos específicos, estoy familiarizado con los mapeadores de entornos, etc., haga clic en EnvironmentsElement

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

De este código, podemos ver que cada campo corresponde a una clase, por ejemplo, los entornos corresponden a una clase de entorno.

public final class Environment {
    
    
  private final String id;
  private final TransactionFactory transactionFactory;
  private final DataSource dataSource;
  }

Los campos aquí corresponden exactamente a la configuración de config.xml

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/fisrt21?useUnicod=true&amp;characterEncoding=utf-8&amp;useSSL=true"/>
                <property name="username" value="root"/>
                <property name="password" value="2020"/>
            </dataSource>
        </environment>
    </environments>

Se puede ver que se realizará una configuración.setXXXX después de obtener el valor al final, entonces, ¿cuál es esta configuración?

  protected Environment environment;

  protected boolean safeRowBoundsEnabled;
  protected boolean safeResultHandlerEnabled = true;
  protected boolean mapUnderscoreToCamelCase;
  protected boolean aggressiveLazyLoading;
  protected boolean multipleResultSetsEnabled = true;
  protected boolean useGeneratedKeys;
  protected boolean useColumnLabel = true;
  protected boolean cacheEnabled = true;
  protected boolean callSettersOnNulls;
  protected boolean useActualParamName = true;
  protected boolean returnInstanceForEmptyRow;
  protected boolean shrinkWhitespacesInSql;
  protected boolean nullableOnForEach;

Descubrí que contiene una serie de parámetros de configuración, así que supongo que contiene algunas capas de configuración de mybatis.
En este proceso, lee todas las configuraciones en el archivo xml en la instancia de la clase de configuración y
ejecuta la compilación una vez finalizada.

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

Puede ver que se devuelve un DefaultSqlSessionFactory. El SqlSessionFactory predeterminado tiene métodos selectone o getmapper. A partir de esto, se puede ver que se ha creado una instancia del SqlSessionFactory principal de esta aplicación mybatis. Confirmó mi sospecha.
En primer lugar, el entorno en config.xml es una URL, así como la configuración del nombre de usuario y la contraseña.
Entonces se puede decir que este paso crea una fuente de datos. El siguiente paso es descubrir cómo se obtiene la declaración SQL.

Análisis inicial del código fuente de Mybatis (2)

Supongo que te gusta

Origin blog.csdn.net/Yoke______/article/details/123956039
Recomendado
Clasificación