[Analysis] MyBatis source Xml configuration file is loaded

Debug entry

XmlConfigBuilderTest found in mybatis source code, run shouldSuccessfullyLoadXMLConfigFile in debug mode ().

initialization

First create XMLConfigBuilder object in the constructor:

  • InputStream by reading the file, generates an XML Document object, XML-related operations beyond the scope of this paper, is skipped

  • Configuration created object stores various configuration information, a number of registration information in the alias mapping method of construction, for example, a key JDBC, value is JdbcTransactionFactory.class

  • Available through ThreadLocal ErrorContext, for saving the context information to facilitate throwing an exception when access to information

Resolution Configuration

Then call XMLConfigBuilder.parse () parse xml file:

  • XMLConfigBuilder.parse (), using the global variables numerals to avoid repeated load, or return the configuration object (the Configuration)

    • . XMLConfigBuilder.parse () parseConfiguration (), parse the configuration file <configuration> of the respective sub-nodes, each child node can not be repeated claim, repeated throws an exception if:

      Element type content "configuration" must match "(properties?, Settings?, TypeAliases?, TypeHandlers?, ObjectFactory?, ObjectWrapperFactory?, ReflectorFactory?, Plugins?, Environments?, DatabaseIdProvider?, Mappers?)"

      • Analytical <properties> node, the node reads the designated properties Properties object file and generate

      • Analytical <settings> node, converted into a Properties object, it is a HashTable. Then do check for key Properties object to see if it is a member of the class of variable Configuration. The inspection method is to have a member variable name setter method, stored in a collection by contains () is determined, If not, it means that <setting> node configuration error, then an exception is thrown

        • Load <settings> node Vfs customized (virtual file system))

        • Loading <settings> Log node custom implementation

      • Analytical <typeAliases> node alias. Only the child node <package> or <typeAlias> node.

        • If the child node is a <typeAlias> , mapping the aliased object class. If no alias is specified, the default alias class.getSimpleName (), if the Alias annotation configuration, the value of notes used as an alias, alias lowercase.

        • If the child node is a <Package> , places the entire package as a unit configured alias

          • Sub-directory under the file path to get the package collection

          • Through the entire collection, if it is the end of the .class file, which is loaded by the class loader

            • Use strategy mode, determine whether this class is a subclass of the Object class is not, then this is the class object added to the result set

          • Traversal result set, if not anonymous class and not an interface and is not a member of the class is to map the alias object class, the default alias class.getSimpleName (), if the Alias ​​annotation configuration, use the value of the notes as alias, use lowercase.

      • Analytical <plugins> node, create an object by reflecting the interceptor, add the object to the interceptor chain configuration object (the ArrayList a)

      • Analytical <objectWrapperFactory> node, by reflection, to generate object factory

      • Analytical <reflectorFactory> node, to produce reflected by the reflector factory, the reflector object class caches information e.g. setter and getter methods set method set

      • The <Setting> the setter method is parsed node configuration to configuration object, calls the configuration of each member variable of the object properties and methods of obtaining getOrDefault value

      • Analytical <environments> node, parsing the database link address, account password configuration, parsing <transactionManager> and <dataSource> node, generating data sources and transaction factory object

      • Analytical < <databaseIdProvider> > node

      • Analytical <typeHandlers> nodes, lookup cache or the alias class.forName obtained TypeHandler class object, then generating object reflector, the object is cached, the structure Map <JavaType, Map <JdbcType, TypeHandler <? >>>, mapping relationship to Java types -> Jdbc type -> TypeHandler. In addition to simultaneously keep a cache structure is the Map <Class <?>, TypeHandler <?> >.

        • If the child node is a <typeHandler>

          • According to first find JavaType name is already cached the class object, if there is no cache hit is reflected by the object class and get cached

          • Gets JdbcType objects by enumerating .valueOf ()

          • According to first find TypeHandler name is already cached the class object, if there is no cache hit is reflected by the object class and get cached

          • Establish JavaType-> JdbcType-> mapping relationship TypeHandler objects, JdbcType allowed to be empty, and can be obtained from the annotation JdbcType

            • Wherein the object instance is configured by reflection TypeHandler

          • Establish TypeHandler.class-> object mapping relationship TypeHandler

        • If the child node is a <Package> , places the entire package as a unit acquired TypeHandler

          • Sub-directory under the file path to get the package collection

          • Through the entire collection, if it is the end of the .class file, which is loaded by the class loader

            • Use strategy mode, determine whether this class is not TypeHandler subclass, then this is the class object added to the result set

          • Traversing the result set, if not anonymous inner classes, not an interface, not an abstract class, the annotation according MappedTypes, MappedJdbcTypes annotation establishing JavaType-> JdbcType-> TypeHandler mapping, wherein allow nulls JdbcType

      • Parsing <mappers> node, read from disk into memory and parsed into xxxMapper.xml relevant configuration objects, embodied in XMLMapperBuilder, in a separate article

appendix

Typical mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--
​
       Copyright 2009-2016 the original author or authors.
​
       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at
​
          http://www.apache.org/licenses/LICENSE-2.0
​
       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
​
-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><properties resource="org/apache/ibatis/databases/blog/blog-derby.properties"/><settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="lazyLoadingEnabled" value="false"/>
        <setting name="multipleResultSetsEnabled" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="useGeneratedKeys" value="false"/>
        <setting name="defaultExecutorType" value="SIMPLE"/>
        <setting name="defaultStatementTimeout" value="25"/>
    </settings><typeAliases>
        <package name="org.apache.ibatis.domain"/>
    </typeAliases>
    <!--<typeAliases>-->
        <!--<typeAlias alias="Author" type="org.apache.ibatis.domain.blog.Author"/>-->
        <!--<typeAlias alias="Blog" type="org.apache.ibatis.domain.blog.Blog"/>-->
        <!--<typeAlias alias="Comment" type="org.apache.ibatis.domain.blog.Comment"/>-->
        <!--<typeAlias alias="Post" type="org.apache.ibatis.domain.blog.Post"/>-->
        <!--<typeAlias alias="Section" type="org.apache.ibatis.domain.blog.Section"/>-->
        <!--<typeAlias alias="Tag" type="org.apache.ibatis.domain.blog.Tag"/>-->
    <!--</typeAliases>-->
    <typeHandlers>
        <typeHandler javaType="String" jdbcType="VARCHAR" handler="org.apache.ibatis.builder.CustomStringTypeHandler"/>
    </typeHandlers><objectFactory type="org.apache.ibatis.builder.ExampleObjectFactory">
        <property name="objectFactoryProperty" value="100"/>
    </objectFactory><plugins>
        <plugin interceptor="org.apache.ibatis.builder.ExamplePlugin">
            <property name="pluginProperty" value="100"/>
        </plugin>
    </plugins><environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="" value=""/>
            </transactionManager>
            <dataSource type="UNPOOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments><mappers>
        <mapper resource="org/apache/ibatis/builder/AuthorMapper.xml"/>
        <mapper resource="org/apache/ibatis/builder/BlogMapper.xml"/>
        <mapper resource="org/apache/ibatis/builder/CachedAuthorMapper.xml"/>
        <mapper resource="org/apache/ibatis/builder/PostMapper.xml"/>
        <mapper resource="org/apache/ibatis/builder/NestedBlogMapper.xml"/>
    </mappers></configuration>
View Code

Unit Test Method

The method is in XmlConfigBuilderTest class:

@Test
void shouldSuccessfullyLoadXMLConfigFile() throws Exception {
  // System.setProperty(XPathParser.KEY_USE_XSD, "true");
  String resource = "org/apache/ibatis/builder/xsd/CustomizedSettingsMapperConfig.xml";
  try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
    XMLConfigBuilder builder = new XMLConfigBuilder(inputStream);
    Configuration config = builder.parse();
​
    assertEquals(AutoMappingBehavior.NONE, config.getAutoMappingBehavior());
    assertEquals(AutoMappingUnknownColumnBehavior.WARNING, config.getAutoMappingUnknownColumnBehavior());
    assertFalse(config.isCacheEnabled());
    assertTrue(config.getProxyFactory() instanceof CglibProxyFactory);
    assertTrue(config.isLazyLoadingEnabled());
    assertTrue(config.isAggressiveLazyLoading());
    assertFalse(config.isMultipleResultSetsEnabled());
    assertFalse(config.isUseColumnLabel());
    assertTrue(config.isUseGeneratedKeys());
    assertEquals(ExecutorType.BATCH, config.getDefaultExecutorType());
    assertEquals(Integer.valueOf(10), config.getDefaultStatementTimeout());
    assertEquals(Integer.valueOf(100), config.getDefaultFetchSize());
    assertTrue(config.isMapUnderscoreToCamelCase());
    assertTrue(config.isSafeRowBoundsEnabled());
    assertEquals(LocalCacheScope.STATEMENT, config.getLocalCacheScope());
    assertEquals(JdbcType.NULL, config.getJdbcTypeForNull());
    assertEquals(new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString", "xxx")), config.getLazyLoadTriggerMethods());
    assertFalse(config.isSafeResultHandlerEnabled());
    assertTrue(config.getDefaultScriptingLanguageInstance() instanceof RawLanguageDriver);
    assertTrue(config.isCallSettersOnNulls());
    assertEquals("mybatis_", config.getLogPrefix());
    assertEquals(Slf4jImpl.class.getName(), config.getLogImpl().getName());
    assertEquals(JBoss6VFS.class.getName(), config.getVfsImpl().getName());
    assertEquals(String.class.getName(), config.getConfigurationFactory().getName());
​
    assertEquals(Author.class, config.getTypeAliasRegistry().getTypeAliases().get("blogauthor"));
    assertEquals(Blog.class, config.getTypeAliasRegistry().getTypeAliases().get("blog"));
    assertEquals(Cart.class, config.getTypeAliasRegistry().getTypeAliases().get("cart"));
​
    assertTrue(config.getTypeHandlerRegistry().getTypeHandler(Integer.class) instanceof CustomIntegerTypeHandler);
    assertTrue(config.getTypeHandlerRegistry().getTypeHandler(Long.class) instanceof CustomLongTypeHandler);
    assertTrue(config.getTypeHandlerRegistry().getTypeHandler(String.class) instanceof CustomStringTypeHandler);
    assertTrue(config.getTypeHandlerRegistry().getTypeHandler(String.class, JdbcType.VARCHAR) instanceof CustomStringTypeHandler);
​
    ExampleObjectFactory objectFactory = (ExampleObjectFactory)config.getObjectFactory();
    assertEquals(1, objectFactory.getProperties().size());
    assertEquals("100", objectFactory.getProperties().getProperty("objectFactoryProperty"));
​
    assertTrue(config.getObjectWrapperFactory() instanceof CustomObjectWrapperFactory);
​
    assertTrue(config.getReflectorFactory() instanceof CustomReflectorFactory);
​
    ExamplePlugin plugin = (ExamplePlugin)config.getInterceptors().get(0);
    assertEquals(1, plugin.getProperties().size());
    assertEquals("100", plugin.getProperties().getProperty("pluginProperty"));
​
    Environment environment = config.getEnvironment();
    assertEquals("development", environment.getId());
    assertTrue(environment.getDataSource() instanceof UnpooledDataSource);
    assertTrue(environment.getTransactionFactory() instanceof JdbcTransactionFactory);
​
    assertEquals("derby", config.getDatabaseId());
​
    assertEquals(4, config.getMapperRegistry().getMappers().size());
    assertTrue(config.getMapperRegistry().hasMapper(CachedAuthorMapper.class));
    assertTrue(config.getMapperRegistry().hasMapper(CustomMapper.class));
    assertTrue(config.getMapperRegistry().hasMapper(BlogMapper.class));
    assertTrue(config.getMapperRegistry().hasMapper(NestedBlogMapper.class));
  } finally {
    // System.clearProperty(XPathParser.KEY_USE_XSD);
  }
}
View Code

A series of default alias

basic type

public TypeAliasRegistry() {
  registerAlias("string", String.class);
​
  registerAlias("byte", Byte.class);
  registerAlias("long", Long.class);
  registerAlias("short", Short.class);
  registerAlias("int", Integer.class);
  registerAlias("integer", Integer.class);
  registerAlias("double", Double.class);
  registerAlias("float", Float.class);
  registerAlias("boolean", Boolean.class);
​
  registerAlias("byte[]", Byte[].class);
  registerAlias("long[]", Long[].class);
  registerAlias("short[]", Short[].class);
  registerAlias("int[]", Integer[].class);
  registerAlias("integer[]", Integer[].class);
  registerAlias("double[]", Double[].class);
  registerAlias("float[]", Float[].class);
  registerAlias("boolean[]", Boolean[].class);
​
  registerAlias("_byte", byte.class);
  registerAlias("_long", long.class);
  registerAlias("_short", short.class);
  registerAlias("_int", int.class);
  registerAlias("_integer", int.class);
  registerAlias("_double", double.class);
  registerAlias("_float", float.class);
  registerAlias("_boolean", boolean.class);
​
  registerAlias("_byte[]", byte[].class);
  registerAlias("_long[]", long[].class);
  registerAlias("_short[]", short[].class);
  registerAlias("_int[]", int[].class);
  registerAlias("_integer[]", int[].class);
  registerAlias("_double[]", double[].class);
  registerAlias("_float[]", float[].class);
  registerAlias("_boolean[]", boolean[].class);
​
  registerAlias("date", Date.class);
  registerAlias("decimal", BigDecimal.class);
  registerAlias("bigdecimal", BigDecimal.class);
  registerAlias("biginteger", BigInteger.class);
  registerAlias("object", Object.class);
​
  registerAlias("date[]", Date[].class);
  registerAlias("decimal[]", BigDecimal[].class);
  registerAlias("bigdecimal[]", BigDecimal[].class);
  registerAlias("biginteger[]", BigInteger[].class);
  registerAlias("object[]", Object[].class);
​
  registerAlias("map", Map.class);
  registerAlias("hashmap", HashMap.class);
  registerAlias("list", List.class);
  registerAlias("arraylist", ArrayList.class);
  registerAlias("collection", Collection.class);
  registerAlias("iterator", Iterator.class);
​
  registerAlias("ResultSet", ResultSet.class);
}
View Code

Other types

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

 

Guess you like

Origin www.cnblogs.com/datartvinci/p/10982865.html