Mybatisソースコードの予備解析(1)

長い間放置されていたmybatisのソースコードガイドですが、今日は簡単にまとめてみます。
ソースコードを読みますか? マクロからミクロの順に読むべきだと思います。必要に応じて、独自のグラフィック処理を追加して、思考をより明確にすることもできます。

マイバティスについての最初の考え

  1. まず、mybatis は運用を簡素化するためのフレームワークです。
  2. その場合、その存在は jdbc 接続を置き換えるため、データベースに接続する基本的な操作を含める必要があります。

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

    }
}

データソース、SQL文、データ操作の3つの部分があると思います。

  • ここでのデータ ソースは、URL、ユーザー名、パスワードを含む構成です。これを介してデータベースに接続できます
  • SQL文は手動で書いたSQL文です
  • データ操作は、接続データベース オブジェクトが SQL オブジェクト ステートメントを取得し、そのステートメントを通じて SQL ステートメントを実行して結果セットを取得するプロセスです。
    これは、非常に基本的な jdbc データベース接続操作です。

mybats フレームワークは jdbc 接続を置き換えるため、これら 3 つのタスクも完了する必要があり、順序は同様ですが、それが正しいかどうかはソース コードで検証する必要があります。それから私はこの質問を受けてソースコードの読み方を入力しました

mabatis ソースコードの最初の読み取り

他の人がどのようにソースコードを読んでいるのかはわかりませんが、私の場合は、デモを書いて、アイデアのデバッグプロセスを実行して、このフレームワークがどのようなプロセスであるかを段階的に確認します。 mybatis
公式ドキュメント
と mybatis のソース コードを 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();
  }
}

このような小さなデモを書き留めて、分析を開始します。
まず、コードの最初の行から開始して、config.xml の構成を inputstream に変換し、sqlsessionFactory メソッドのビルドを実行します。mybatis に詳しい人なら、すべての MyBatis ベースのアプリケーションが SqlSessionFactory のインスタンスを中心にしていることを知っています
SqlSessionFactory のインスタンスは、SqlSessionFactoryBuilder を通じて取得できます。SqlSessionFactoryBuilder は、XML 構成ファイルまたは事前構成された構成インスタンスから SqlSessionFactory インスタンスを構築できます。
このステップは、config.xml の分析を通じて SqlSessionFactory のインスタンスを構築するものであり、これは固有のものです。

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

明らかに XMLConfigBuilder クラスがあります。クラス名から、これが何のためにあるのかおおよそ推測できます。これはおそらく XML ファイルを解析するために使用されるツール クラスです。明らかに、ビルドする前に XMLConfigBuilder.parse() メソッドが実行されます。クリックしてご覧ください

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

parseConfiguration メソッドは、構成を解析するために呼び出されます。
いくつかの具体的なメソッドを見てみましょう。私は環境マッパーなどに精通しています。environmentElement をクリックします。

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

このコードから、各フィールドがクラスに対応していることがわかります。たとえば、環境は環境クラスに対応します。

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

ここのフィールドは、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>

最後に値を取得した後にconfiguration.setXXXXが行われることが分かりますが、この設定は何でしょうか?

  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;

このような一連の設定パラメータが含まれていることがわかりました。そのため、mybatis のいくつかの設定層が含まれていると思われます。
このプロセスでは、xml ファイル内のすべての構成を構成クラスのインスタンスに読み取り、
完了後にビルドを実行します。

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

DefaultSqlSessionFactory が返されることがわかります。デフォルトの SqlSessionFactory には selectone メソッドまたは getmapper メソッドが含まれています。このことから、この mybatis アプリケーションのコア SqlSessionFactory のインスタンスが作成されたことがわかります。私の疑惑を裏付けました。
まず、config.xml 内の環境は URL であり、ユーザー名とパスワードの構成も含まれます。
したがって、このステップはデータ ソースを作成すると言えます。次のステップは、SQL ステートメントがどのように取得されるかを調べることです。

Mybatisソースコードの初期解析(2)

おすすめ

転載: blog.csdn.net/Yoke______/article/details/123956039