blog

Mybatisソースコード(a) --- SqlSessionFactoryBuilder (コンフィギュレーションファイルの取得)

mybaitsの使用では、最初のオブジェクトを作成します、オブジェクトから構築され、オブジェクトの構築メソッドを呼び出すオブジェクトを構築するストリームファイルのグローバルXML構成をロードします。 ...

Apr 17, 2020 · 9 min. read
シェア

mybaitsの使用では、最初のSqlSessionFactoryオブジェクトを作成します、オブジェクトは、SqlSessionFactoryBuilderオブジェクトは、オブジェクトのビルドメソッドを呼び出すストリームファイルのグローバルXML構成をロードするSqlSessionFactoryオブジェクトを構築します。

 //コンフィギュレーションを読み込む.xml
 Reader reader = Resources.getResourceAsReader("conf.xml");
 //セッション・ファクトリを作成する
 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);

SqlSessionFactoryBuilder

public SqlSessionFactory build(Reader reader) {
 return build(reader, null, null);
 }
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
 try {
 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
 return build(parser.parse());
 } catch (Exception e) {
 throw ExceptionFactory.wrapException("Error building SqlSession.", e);
 } finally {
 ErrorContext.instance().reset();
 try {
 reader.close();
 } catch (IOException e) {
 // Intentionally ignore. Prefer previous error.
 }
 }
 }

XMLConfigBuilderparseConfiguration

XMLConfigBuilder クラス名が見えますが、これは XML 構成ファイル クラスを解析するために使用され、BaseBuilder の親クラスです。

public class XMLConfigBuilder extends BaseBuilder{
...
}

XMLConfigBuilder親クラス BaseBuilder

BaseBuilderはまた、多くのサブクラスが含まれています、これらのサブクラスは、MyBatis設定ファイルを解析するために使用され、それらは一緒にBaseBuilderの親クラスを介してグローバルな設定オブジェクトを維持するために、XMLConfigBuilderの役割は、グローバルな設定ファイルを解析することです。BaseBuilder の他のサブクラスを呼び出して他の設定ファイルを解析し、最終的な Configuration オブジェクトを生成します。ここで、BaseBuilder のコンストラクタのパラメータが初期化された Configuration オブジェクトであること、Configuration オブジェクトの初期化時に、組み込みのエイリアスレジストリ TypeAliasRegistry がデフォルトのエイリアスを登録することは注目に値します。

public Configuration() {
 typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
 typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
 typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
 typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
 typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
 typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
 typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
 typeAliasRegistry.registerAlias("LRU", LruCache.class);
 typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
 typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
 typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
 typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
 typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
 typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
 typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
 typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
 typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
 typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
 typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
 typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
 typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
 typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
 languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
 languageRegistry.register(RawLanguageDriver.class);
 }

XPathParserクラス parseConfiguration.xml

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
 this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
 }

フィールド

private Document document ; // Document  
private boolean validation; / / バリデーションを有効にするかどうか
private EntityResolver entityResolver ; / ローカルの DTD ファイルを読み込む
pruvate Properties variables ; // mybatis -config.xml の < propteries > タグで定義されたキー・ペアのセットを読み込む。
private XPath xpath ; // XPath  
  • Document Document オブジ ェ ク ト は XML 文書全体を表 し 、 文書ツ リ ーのルー ト であ り 、 文書デー タ への初期ア ク セ ス を提供 し ます。
  • EntityResolverは、mybatis-config.xml設定ファイルを解析する場合、デフォルトのネットワークでは、http://mybatis.org/dtd/mybatis-3- config.dtdこのDTDドキュメントをロードします。ネットワークが比較的遅い場合、検証処理に時間がかかります。実際には、EntityResolver インタフェース・オブジェクトは、ローカルの DTD ファイルを読み込むようにあらかじめ設定されていることが多く、ネットワーク経由で DTD ファイルを読み込む必要性を回避しています。
  • XPath XPath は、XML 文書のクエリ用に設計された言語で、DOM 構文解析メソッドと組み合わせて XML 文書の構文解析を行うことができます。
  • validation このフラグは、ドキュメントをパースするときにパーサーがドキュメントを検証するかどうかを設定します。
  • variables url や resource 経由で読み込まれたものも含め、設定ファイルの対応するノードの下で定義されたキーと値のペアのコレクション。

コンストラクタ

XPathParser クラスは一連のコンストラクタを提供しており、 すべてのコンストラクタは共通のコンストラクタ () メソッドで関連するフィールド属性の初期化を行います。大まかに4つのカテゴリに分けることができます

  • パラメータとしてのドキュメント
  • パラメータとしてInputStream
  • パラメータとしてのリーダー
  • パラメータとして文字列
 public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
 commonConstructor(validation, variables, entityResolver);
 this.document = createDocument(new InputSource(reader));
 }

createDocument

このメソッドは、入力ソースに基づいて Document オブジェクトを作成します。Document オブジェクトの作成手順は以下のとおりです。

  • DocumentBuilderFactory オブジェクトを作成し、関連するパラメータを設定します。DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  • Document オブジェクトを解析します。builder.parse(inputSource);

コードは以下のとおりです。

 private Document createDocument(InputSource inputSource) {
 // important: this must only be called AFTER common constructor
 try {
 	//DocumentBuilderFactoryインスタンス・オブジェクトを生成する
 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 //DTD検証を有効にするかどうかを設定する
 factory.setValidating(validation);
 //XML名前空間をサポートするかどうかを設定する
 factory.setNamespaceAware(false);
 //コメントを無視するようにパーサーを設定する
 factory.setIgnoringComments(true);
 /**
 * setは要素の内容から空白を取り除かなければならない(「空白を無視する」と呼ばれることもある)”,XML Rec 2を参照のこと .10)。
 * スペースが要素内容に直接含まれ、要素内容が1つの要素の内容パターンのみである場合にのみ、XMLファイルを読み込むことに注意。,
 * 空白を削除する(XML Rec 3参照).2.1).この設定はコンテンツスキーマに依存するため、パーサがバリデーションモードであることを要求する。デフォルトでは、この値はfalseに設定されている。
 */
 factory.setIgnoringElementContentWhitespace(false);
 /**
 * このコードによって生成されるパーサーが、CDATAノードをTextノードに変換し、隣接するTextノードに追加することを指定する。デフォルトでは、この値は false に設定されている。
 */
 factory.setCoalescing(false);
 /**
 * このコードによって生成されるパーサーがエンティティ参照ノードを拡張することを指定する。デフォルトでは、この値は true に設定されている。
 */
 factory.setExpandEntityReferences(true);
 //DocumentBuilderインスタンス・オブジェクトを生成する
 DocumentBuilder builder = factory.newDocumentBuilder();
 //解析対象の XML ドキュメントに存在するエンティティを解析するために EntityResolver を使用することを指定する。これを NULL に設定すると、基礎となる実装がそれ自身のデフォルトの実装と動作を使用するようになる。
 builder.setEntityResolver(entityResolver);
 //パーサが使用する ErrorHandler を指定する。 これを null に設定すると、基礎となる実装がそれ自身のデフォルトの実装と動作を使用するようになる。
 builder.setErrorHandler(new ErrorHandler() {
 @Override
 public void error(SAXParseException exception) throws SAXException {
 throw exception;
 }
 @Override
 public void fatalError(SAXParseException exception) throws SAXException {
 throw exception;
 }
 @Override
 public void warning(SAXParseException exception) throws SAXException {
 }
 });
 return builder.parse(inputSource);
 } catch (Exception e) {
 throw new BuilderException("Error creating document instance. Cause: " + e, e);
 }
 }

commonConstructor

private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
 this.validation = validation;
 this.entityResolver = entityResolver;
 this.variables = variables;
 XPathFactory factory = XPathFactory.newInstance();
 this.xpath = factory.newXPath();
 }

evalXXX

XPathParser クラスは、主に boolean, short, long, int, String, Node などの型の情報をパースするための evalXXX メソッドを提供しています。一番下はevaluate()メソッドで実装されています。このうち、evalString()メソッドは、PropertyParser.parse()を呼び出してプレースホルダを処理し、evalNode()、evalNodes()メソッドは、パース結果に応じてXNodeオブジェクトを生成します。具体的な作成プロセスは、XNodeクラスのソースコード解析で学ぶことができます。

XNode

XNodeクラスは、設定ファイルの要素ノードの情報に対応します。

 //org.w3c.dorn.Node 
 private final Node node;
 //Nodeノード名
 private final String name;
 //ノードの内容
 private final String body;
 //ノード属性コレクション
 private final Properties attributes;
 //コンフィギュレーション・ファイル<properties>ノードの下に定義されたキー・ペア
 private final Properties variables;
 //XPathParserオブジェクト、この XPathParser オブジェクトから生成された現在の XNode オブジェクトを読み込む
 private final XPathParser xpathParser;
を実行し、ビルドメソッドを確認します。パラメータはConfigurationで、parseメソッドはConfigurationオブジェクトを返すと推測できます。
parseメソッドのコード。
public Configuration parse() {
 if (parsed) {
 throw new BuilderException("Each XMLConfigBuilder can only be used once.");
 }
 parsed = true;
 // <configuraton>タグ付けされたルート・ノード
 parseConfiguration(parser.evalNode("/configuration"));
 return configuration;
 }

ここでは、Xparserクラスの作成を使用してparseConfigurationメソッドを介して見つけることができる、XMLグローバル設定ファイルは、各ノードの情報を読み出すには、Configurationオブジェクトに保存され、Configurationは、次の初期化で行われました:

private void parseConfiguration(XNode root) {
 try {
 //issue #117 read properties first
 propertiesElement(root.evalNode("properties"));
 Properties settings = settingsAsProperties(root.evalNode("settings"));
 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);
 }
 }
  • parseDocument オブジェクト。 builder.parse(inputSource);
  • 設定
  • settings
  • typeAliases 型エイリアス
  • typeHandlers 型プロセッサ
  • objectFactory オブジェクト・ファクトリー
  • plugins
  • environments
  • databaseIdProvider データベース・ベンダーの識別

この時点で、設定ファイルの読み込みを開始できます。

簡単に言うと、次のようになります。

Mybatisのソースコード --- SqlSessionFactoryBuilder(設定ファイルの取得)

Mybatisソースコード - parseConfiguration 読み込みXMLファイル

Mybatis のソース・コード --- SqlSession による sql クエリの実行

Mybatis のソースコード --- SqlSession による動的エージェントの完成

Mybatisのソースコード --- SqlSessionの4つの主要なオブジェクト

Mybatis ソース・コード --- キャッシュ

個人的な意見です。議論へようこそ、

Read next

JVMのクラス・ローディング・プロセスをより深く理解する

その名が示すように、クラス・ローダーはJavaクラスをJava仮想マシンにロードするために使用されます。一般的に言って、Java仮想マシンは以下の方法でJavaクラスを使用します。.javaファイルはコンパイラによってコンパイルされた後、バイトコードの.classファイルに変換されます。クラス・ローダーは、.class ファイルを読み取り、Class クラスのインスタンスに変換します。このような各インスタンスは、...

Apr 16, 2020 · 3 min read