Analyse préliminaire du code source de Mybatis (1)

Le guide du code source de mybatis qui a été longtemps mis de côté, je vais aujourd'hui en faire un petit résumé.
Lire le code source ?Je pense que cela devrait être fait dans l'ordre du macro au micro. Si nécessaire, vous pouvez même ajouter votre propre procédé graphique pour rendre vos idées plus claires.

Premières réflexions sur mybatis

  1. Tout d’abord, mybatis est un framework pour simplifier les opérations.
  2. Ensuite son existence remplace la connexion jdbc, elle doit donc inclure les opérations de base de connexion à la base de données

À propos du fonctionnement 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();

    }
}

Je pense qu'il y a trois parties : la source de données, l'instruction SQL et l'opération de données.

  • La source de données ici est une configuration comprenant l'URL, le nom d'utilisateur et le mot de passe. Grâce à cela, vous pouvez vous connecter à la base de données
  • L'instruction SQL est une instruction SQL que j'ai écrite manuellement
  • L'opération de données est le processus dans lequel mon objet de base de données de connexion obtient l'instruction d'objet SQL, puis exécute l'instruction SQL via l'instruction pour obtenir un ensemble de résultats.
    Il s'agit d'une opération de connexion à la base de données jdbc que je trouve très basique.

Puisque le framework mybats remplace la connexion jdbc, il doit également effectuer ces trois tâches, et l'ordre est similaire. Qu'il soit correct ou non doit être vérifié dans le code source. Ensuite, j'ai répondu à cette question et suis entré dans la lecture du code source.

Première lecture du code source de mabatis


Je ne sais pas comment les autres lisent un code source. Pour moi, j'écris simplement une démo, puis je passe par le processus de débogage de l'idée pour voir de quel type de processus il s'agit
. Extrayez le code source de mybatis depuis 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();
  }
}

Écrivez une si petite démo et commencez à l’analyser.
Tout d'abord, à partir de la première ligne de code, convertissez la configuration de config.xml en inputstream puis exécutez la construction d'une méthode sqlsessionFactory. Toute personne familiarisée avec
mybatis sait que chaque application basée sur MyBatis est centrée sur une instance de SqlSessionFactory. Les instances de SqlSessionFactory peuvent être obtenues via SqlSessionFactoryBuilder. SqlSessionFactoryBuilder peut créer une instance SqlSessionFactory à partir d'un fichier de configuration XML ou d'une instance de configuration préconfigurée.
Cette étape consiste à construire une instance de SqlSessionFactory en analysant config.xml, et elle est unique.

Voyons quels points sont construits dans la méthode build.

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

Évidemment, il existe une classe XMLConfigBuilder. D'après le nom de la classe, je peux deviner à peu près à quoi sert cette chose. Il s'agit probablement d'une classe d'outils utilisée pour analyser les fichiers XML. Évidemment, une méthode XMLConfigBuilder.parse() est exécutée avant la construction. Cliquez pour voir

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

La méthode parseConfiguration est appelée pour analyser la configuration.
Jetons un coup d'œil à quelques méthodes spécifiques. Celles que je connais sont les mappeurs d'environnements, etc. Cliquez sur environnementsElement

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

A partir de ce code, nous pouvons voir que chaque champ correspond à une classe. Par exemple, environnements correspond à une classe d'environnement.

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

Les champs ici correspondent à la configuration 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>

Vous pouvez voir qu'après avoir finalement obtenu la valeur, une configuration.setXXXX sera effectuée. Alors, quelle est exactement cette configuration ?

  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;

On constate qu'il contient une telle série de paramètres de configuration, alors devinez quelques couches de configuration de l'ensemble de son mybatis.
Dans ce processus, il lit toute la configuration du fichier XML dans l'instance de la classe de configuration et
exécute build après la fin.

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

Vous pouvez voir qu'un DefaultSqlSessionFactory est renvoyé. Le SqlSessionFactory par défaut a des méthodes selectone ou getmapper. À partir de là, on peut voir qu'une instance du noyau SqlSessionFactory de cette application mybatis a été créée. Confirmé mes soupçons.
Tout d'abord, l'environnement dans config.xml est une URL, ainsi que la configuration du nom d'utilisateur et du mot de passe.
On peut donc dire que cette étape crée la source de données. L'étape suivante consiste à découvrir comment l'instruction SQL est obtenue.

Analyse préliminaire du code source de Mybatis (2)

Je suppose que tu aimes

Origine blog.csdn.net/Yoke______/article/details/123956039
conseillé
Classement