Mybatis源码解析之标签的解析

阅读须知

  • Mybatis源码版本:3.4.4
  • 文章中使用/* */注释的方法会做深入分析

正文

Mybatis是我们日常开发过程中经常使用的ORM框架,读者可以首先参考Mybatis中文官方文档来看一下Mybatis的使用示例,首先要通过SqlSessionFactoryBuilder来构建SqlSessionFactory,我们就以SqlSessionFactory的构建为入口来分析Mybatis源码:
SqlSessionFactoryBuilder:

public SqlSessionFactory build(InputStream inputStream) {
    /* 构建SqlSessionFactory */
    return build(inputStream, null, null);
}

SqlSessionFactoryBuilder:

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        /* 解析配置,构建SqlSessionFactory */
        return build(parser.parse());
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
        ErrorContext.instance().reset();
        try {
            inputStream.close();
        } catch (IOException e) {
        }
    }
}

XMLConfigBuilder:

public Configuration parse() {
    if (parsed) {
        throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    /* 解析配置 */
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
}

关于配置的功能及使用方法,请参考官方文档,地址已经给出。
XMLConfigBuilder:

private void parseConfiguration(XNode root) {
    try {
        /* 解析properties标签 */
        propertiesElement(root.evalNode("properties"));
        /* 解析settings标签 */
        Properties settings = settingsAsProperties(root.evalNode("settings"));
        /* 设置自定义VFS */
        loadCustomVfs(settings);
        /* 解析typeAliases标签 */
        typeAliasesElement(root.evalNode("typeAliases"));
        /* 解析plugins标签 */
        pluginElement(root.evalNode("plugins"));
        /* 解析objectFactory标签 */
        objectFactoryElement(root.evalNode("objectFactory"));
        /* 解析objectWrapperFactory标签 */
        objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
        /* 解析reflectorFactory标签 */
        reflectorFactoryElement(root.evalNode("reflectorFactory"));
        /* 将settings配置放入configuration对象中 */
        settingsElement(settings);
        /* 解析environments标签 */
        environmentsElement(root.evalNode("environments"));
        /* 解析databaseIdProvider标签 */
        databaseIdProviderElement(root.evalNode("databaseIdProvider"));
        /* 解析typeHandlers标签 */
        typeHandlerElement(root.evalNode("typeHandlers"));
        /* 解析mappers标签 */
        mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
        throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
}

XMLConfigBuilder:

private void propertiesElement(XNode context) throws Exception {
    if (context != null) {
        // 将子标签的name和value属性作为键值对放入Properties对象中
        Properties defaults = context.getChildrenAsProperties();
        // 获取resource属性
        String resource = context.getStringAttribute("resource");
        // 获取url属性
        String url = context.getStringAttribute("url");
        // 两者不能同时存在
        if (resource != null && url != null) {
            throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.");
        }
        if (resource != null) {
            // 如果resource不为空则加载resource配置的配置文件
            defaults.putAll(Resources.getResourceAsProperties(resource));
        } else if (url != null) {
            // 如果url不为空则加载url配置的资源
            defaults.putAll(Resources.getUrlAsProperties(url));
        }
        Properties vars = configuration.getVariables();
        if (vars != null) {
            // 如果定义了configuration对象的变量同样加入配置中
            defaults.putAll(vars);
        }
        // 将配置放入parser和configuration对象中
        parser.setVariables(defaults);
        configuration.setVariables(defaults);
    }
}

XMLConfigBuilder:

private Properties settingsAsProperties(XNode context) {
    if (context == null) {
        return new Properties();
    }
    // 将子标签的name和value属性作为键值对放入Properties对象中
    Properties props = context.getChildrenAsProperties();
    MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
    // 校验Configuration类中是否有对应的setter方法
    for (Object key : props.keySet()) {
        if (!metaConfig.hasSetter(String.valueOf(key))) {
            throw new BuilderException("The setting " + key + " is not known.  Make sure you spelled it correctly (case sensitive).");
        }
    }
    return props;
}

XMLConfigBuilder:

private void loadCustomVfs(Properties props) throws ClassNotFoundException {
    // 将用户自定义VFS放入configuration对象中
    String value = props.getProperty("vfsImpl");
    if (value != null) {
        String[] clazzes = value.split(",");
        for (String clazz : clazzes) {
            if (!clazz.isEmpty()) {
                @SuppressWarnings("unchecked")
                Class<? extends VFS> vfsImpl = (Class<? extends VFS>)Resources.classForName(clazz);
                configuration.setVfsImpl(vfsImpl);
            }
        }
    }
}

这里提到了Mybatis VFS,简单介绍一下,它提供一个非常简单的API,用于访问应用程序服务器内的资源。
XMLConfigBuilder:

private void typeAliasesElement(XNode parent) {
    if (parent != null) {
        for (XNode child : parent.getChildren()) {
            if ("package".equals(child.getName())) {
                String typeAliasPackage = child.getStringAttribute("name");
                /* 指定包名的类别名注册 */
                configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
            } else {
                String alias = child.getStringAttribute("alias");
                String type = child.getStringAttribute("type");
                try {
                    Class<?> clazz = Resources.classForName(type);
                    if (alias == null) {
                        /* 没有指定别名的类别名注册 */
                        typeAliasRegistry.registerAlias(clazz);
                    } else {
                        /* 指定别名的类别名注册 */
                        typeAliasRegistry.registerAlias(alias, clazz);
                    }
                } catch (ClassNotFoundException e) {
                    throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
                }
            }
        }
    }
}

TypeAliasRegistry:

public void registerAliases(String packageName){
    /* 根据包名注册类别名 */
    registerAliases(packageName, Object.class);
}

TypeAliasRegistry:

public void registerAliases(String packageName, Class<?> superType){
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    // 加载包下面的类
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
    for(Class<?> type : typeSet){
        // 非匿名类,非接口类,非成员类
        if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
            /* 注册类别名 */
            registerAlias(type);
        }
    }
}

TypeAliasRegistry:

public void registerAlias(Class<?> type) {
    String alias = type.getSimpleName();
    // 如果注解了@Alias,则取注解的值作为别名
    Alias aliasAnnotation = type.getAnnotation(Alias.class);
    if (aliasAnnotation != null) {
        alias = aliasAnnotation.value();
    } 
    /* 注册类别名 */
    registerAlias(alias, type);
}

TypeAliasRegistry:

public void registerAlias(String alias, Class<?> value) {
    if (alias == null) {
        throw new TypeException("The parameter alias cannot be null");
    }
    // 别名转成小写
    String key = alias.toLowerCase(Locale.ENGLISH);
    // 如果已经包含当前别名,并且不为null,并且新值和原来的值不一样,抛出异常
    if (TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !TYPE_ALIASES.get(key).equals(value)) {
        throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");
    }
    // 将键值映射关系放入别名映射中
    TYPE_ALIASES.put(key, value);
}

TypeAliasRegistry:

public void registerAlias(String alias, String value) {
    try {
        // 在指定别名的情况下同样也是调用上面的方法进行注册
        registerAlias(alias, Resources.classForName(value));
    } catch (ClassNotFoundException e) {
        throw new TypeException("Error registering type alias "+alias+" for "+value+". Cause: " + e, e);
    }
}

Mybatis默认为我们注册了很多别名,在构造TypeAliasRegistry对象时:

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

在构造Configuration对象时:

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

这些别名我们都是可以直接使用的。
XMLConfigBuilder:

private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
        for (XNode child : parent.getChildren()) {
            // 获取interceptor属性配置的类名或者类别名
            String interceptor = child.getStringAttribute("interceptor");
            // 将子标签的name和value属性作为键值对放入Properties对象中
            Properties properties = child.getChildrenAsProperties();
            // 反射实例化
            Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
            // 为拦截器设置用户指定的property配置
            interceptorInstance.setProperties(properties);
            // 将拦截器添加到configuration对象中
            configuration.addInterceptor(interceptorInstance);
        }
    }
}

XMLConfigBuilder:

private void objectFactoryElement(XNode context) throws Exception {
    if (context != null) {
        // 获取type属性配置的类名或者类别名
        String type = context.getStringAttribute("type");
        // 将子标签的name和value属性作为键值对放入Properties对象中
        Properties properties = context.getChildrenAsProperties();
        // 反射实例化
        ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance();
        // 为ObjectFactory设置用户指定的property配置
        factory.setProperties(properties);
        // 将ObjectFactory设置到configuration对象中
        configuration.setObjectFactory(factory);
    }
}

XMLConfigBuilder:

private void objectWrapperFactoryElement(XNode context) throws Exception {
    if (context != null) {
        // 获取type属性配置的类名或者类别名
        String type = context.getStringAttribute("type");
        // 反射实例化
        ObjectWrapperFactory factory = (ObjectWrapperFactory) resolveClass(type).newInstance();
        // 将ObjectWrapperFactory设置到configuration对象中
        configuration.setObjectWrapperFactory(factory);
    }
}

XMLConfigBuilder:

private void reflectorFactoryElement(XNode context) throws Exception {
    if (context != null) {
        // 获取type属性配置的类名或者类别名
        String type = context.getStringAttribute("type");
        // 反射实例化
        ReflectorFactory factory = (ReflectorFactory) resolveClass(type).newInstance();
        // 将ReflectorFactory设置到configuration对象中
        configuration.setReflectorFactory(factory);
    }
}

XMLConfigBuilder:

private void settingsElement(Properties props) throws Exception {
    configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
    configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
    configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
    configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
    configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
    configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
    configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
    configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
    configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
    configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
    configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
    configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
    configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
    configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
    configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
    configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
    configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
    configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
    configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
    configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
    configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
    configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
    configuration.setLogPrefix(props.getProperty("logPrefix"));
    @SuppressWarnings("unchecked")
    Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty("logImpl"));
    configuration.setLogImpl(logImpl);
    configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
}

这里就是将settings对应的配置设置到configuration对象中。
XMLConfigBuilder:

private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
        if (environment == null) {
            // 获取environment默认配置id
            environment = context.getStringAttribute("default");
        }
        for (XNode child : context.getChildren()) {
            // 获取子标签environment的id属性
            String id = child.getStringAttribute("id");
            // 判断与默认配置id是否相同
            if (isSpecifiedEnvironment(id)) {
                /* 解析transactionManager子标签 */
                TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
                /* 解析dataSource子标签 */
                DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
                DataSource dataSource = dsFactory.getDataSource();
                Environment.Builder environmentBuilder = new Environment.Builder(id)
                .transactionFactory(txFactory)
                .dataSource(dataSource);
                // 构建Environment对象并设置到configuration对象中
                configuration.setEnvironment(environmentBuilder.build());
            }
        }
    }
}

XMLConfigBuilder:

private TransactionFactory transactionManagerElement(XNode context) throws Exception {
    if (context != null) {
        // 获取type属性配置的类名或者类别名
        String type = context.getStringAttribute("type");
        // 将子标签的name和value属性作为键值对放入Properties对象中
        Properties props = context.getChildrenAsProperties();
        // 反射实例化
        TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();
        // 为TransactionFactory设置用户指定的property配置
        factory.setProperties(props);
        return factory;
    }
    throw new BuilderException("Environment declaration requires a TransactionFactory.");
}

XMLConfigBuilder:

private DataSourceFactory dataSourceElement(XNode context) throws Exception {
    if (context != null) {
        // 获取type属性配置的类名或者类别名
        String type = context.getStringAttribute("type");
        // 将子标签的name和value属性作为键值对放入Properties对象中
        Properties props = context.getChildrenAsProperties();
        // 反射实例化
        DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();
        // 为DataSourceFactory设置用户指定的property配置
        factory.setProperties(props);
        return factory;
    }
    throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}

XMLConfigBuilder:

private void databaseIdProviderElement(XNode context) throws Exception {
    DatabaseIdProvider databaseIdProvider = null;
    if (context != null) {
        // 获取type属性配置的类名或者类别名
        String type = context.getStringAttribute("type");
        if ("VENDOR".equals(type)) {
            // 这里的DB_VENDOR类别名是在构造Configuration对象时注册的,对应的类是VendorDatabaseIdProvider
            type = "DB_VENDOR";
        }
        // 将子标签的name和value属性作为键值对放入Properties对象中
        Properties properties = context.getChildrenAsProperties();
        // 反射实例化
        databaseIdProvider = (DatabaseIdProvider) resolveClass(type).newInstance();
        // 为DatabaseIdProvider设置用户指定的property配置
        databaseIdProvider.setProperties(properties);
    }
    Environment environment = configuration.getEnvironment();
    if (environment != null && databaseIdProvider != null) {
        // 获取databaseId
        String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
        configuration.setDatabaseId(databaseId); // 设置到configuration对象中
    }
}

XMLConfigBuilder:

private void typeHandlerElement(XNode parent) throws Exception {
    if (parent != null) {
        for (XNode child : parent.getChildren()) {
            if ("package".equals(child.getName())) {
                String typeHandlerPackage = child.getStringAttribute("name"); // 包名
                /* 根据包名加载类型处理器 */
                typeHandlerRegistry.register(typeHandlerPackage);
            } else {
                String javaTypeName = child.getStringAttribute("javaType");
                String jdbcTypeName = child.getStringAttribute("jdbcType");
                String handlerTypeName = child.getStringAttribute("handler");
                // 获取javaType属性配置的类名或者类别名
                Class<?> javaTypeClass = resolveClass(javaTypeName);
                // 根据jdbcType配置的名称在枚举找到对应的枚举值
                JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
                // 获取handler属性配置的类名或者类别名
                Class<?> typeHandlerClass = resolveClass(handlerTypeName);
                if (javaTypeClass != null) {
                    if (jdbcType == null) {
                        /* 注册类型处理器 */
                        typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
                    } else {
                        /* 注册类型处理器 */
                        typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
                    }
                } else {
                    /* 注册类型处理器 */
                    typeHandlerRegistry.register(typeHandlerClass);
                }
            }
        }
    }
}

TypeHandlerRegistry:

public void register(String packageName) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    // 加载包下面的类
    resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
    Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
    for (Class<?> type : handlerSet) {
        // 非匿名类,非接口类,非abstract修饰的类
        if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
            register(type); /* 注册类型处理器 */
        }
    }
}

TypeHandlerRegistry:

public void register(Class<?> typeHandlerClass) {
    boolean mappedTypeFound = false;
    MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);
    // 如果注解了@MappedTypes,则使用注解属性值作为javaType
    if (mappedTypes != null) {
        for (Class<?> javaTypeClass : mappedTypes.value()) {
            /* 注册类型处理器 */
            register(javaTypeClass, typeHandlerClass);
            mappedTypeFound = true;
        }
    }
    if (!mappedTypeFound) {
        /* 获取TypeHandler实例,注册类型处理器 */
        register(getInstance(null, typeHandlerClass));
    }
}

TypeHandlerRegistry:

public void register(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
    /* 获取TypeHandler实例,注册类型处理器 */
    register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass));
}

TypeHandlerRegistry:

public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
    if (javaTypeClass != null) {
        try {
            // 如果有javaType,则将javaType作为参数实例化类型处理器
            Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
            return (TypeHandler<T>) c.newInstance(javaTypeClass);
        } catch (NoSuchMethodException ignored) {
        } catch (Exception e) {
            throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
        }
    }
    try {
        // 无参构造方法实例化类型处理器
        Constructor<?> c = typeHandlerClass.getConstructor();
        return (TypeHandler<T>) c.newInstance();
    } catch (Exception e) {
        throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
    }
}

TypeHandlerRegistry:

private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {
    // 获取类型处理器上的@MappedJdbcTypes注解信息
    MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
    if (mappedJdbcTypes != null) {
        for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
            /* 遍历注解的value属性配置的JdbcType数组作为jdbcType注册类型处理器 */
            register(javaType, handledJdbcType, typeHandler);
        }
        if (mappedJdbcTypes.includeNullJdbcType()) {
            /* 如果注解配置了允许包括null值的jdbcType则注册jdbcType为null的类型处理器 */
            register(javaType, null, typeHandler);
        }
    } else {
        /* 注册jdbcType为null的类型处理器 */
        register(javaType, null, typeHandler);
    }
}

TypeHandlerRegistry:

private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
    if (javaType != null) {
        Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType);
        if (map == null) {
            map = new HashMap<JdbcType, TypeHandler<?>>();
            TYPE_HANDLER_MAP.put(javaType, map);
        }
        map.put(jdbcType, handler);
    }
    ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);
}

注册的过程就是将对应jdbcType、javaType、typeHandler三者的对应关系存入映射中。另外几个重载的注册类型处理器的方法都大同小异,就不做赘述了,另外在构造TypeHandlerRegistry时,Mybatis注册一些默认的类型处理器:

public TypeHandlerRegistry() {
    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());
    register(Byte.class, new ByteTypeHandler());
    register(byte.class, new ByteTypeHandler());
    register(JdbcType.TINYINT, new ByteTypeHandler());
    register(Short.class, new ShortTypeHandler());
    register(short.class, new ShortTypeHandler());
    register(JdbcType.SMALLINT, new ShortTypeHandler());
    register(Integer.class, new IntegerTypeHandler());
    register(int.class, new IntegerTypeHandler());
    register(JdbcType.INTEGER, new IntegerTypeHandler());
    register(Long.class, new LongTypeHandler());
    register(long.class, new LongTypeHandler());
    register(Float.class, new FloatTypeHandler());
    register(float.class, new FloatTypeHandler());
    register(JdbcType.FLOAT, new FloatTypeHandler());
    register(Double.class, new DoubleTypeHandler());
    register(double.class, new DoubleTypeHandler());
    register(JdbcType.DOUBLE, new DoubleTypeHandler());
    register(Reader.class, new ClobReaderTypeHandler());
    register(String.class, new StringTypeHandler());
    register(String.class, JdbcType.CHAR, new StringTypeHandler());
    register(String.class, JdbcType.CLOB, new ClobTypeHandler());
    register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
    register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
    register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
    register(JdbcType.CHAR, new StringTypeHandler());
    register(JdbcType.VARCHAR, new StringTypeHandler());
    register(JdbcType.CLOB, new ClobTypeHandler());
    register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
    register(JdbcType.NVARCHAR, new NStringTypeHandler());
    register(JdbcType.NCHAR, new NStringTypeHandler());
    register(JdbcType.NCLOB, new NClobTypeHandler());
    register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
    register(JdbcType.ARRAY, new ArrayTypeHandler());
    register(BigInteger.class, new BigIntegerTypeHandler());
    register(JdbcType.BIGINT, new LongTypeHandler());
    register(BigDecimal.class, new BigDecimalTypeHandler());
    register(JdbcType.REAL, new BigDecimalTypeHandler());
    register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
    register(JdbcType.NUMERIC, new BigDecimalTypeHandler());
    register(InputStream.class, new BlobInputStreamTypeHandler());
    register(Byte[].class, new ByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
    register(byte[].class, new ByteArrayTypeHandler());
    register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
    register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.BLOB, new BlobTypeHandler());
    register(Object.class, UNKNOWN_TYPE_HANDLER);
    register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
    register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
    register(Date.class, new DateTypeHandler());
    register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
    register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
    register(JdbcType.TIMESTAMP, new DateTypeHandler());
    register(JdbcType.DATE, new DateOnlyTypeHandler());
    register(JdbcType.TIME, new TimeOnlyTypeHandler());
    register(java.sql.Date.class, new SqlDateTypeHandler());
    register(java.sql.Time.class, new SqlTimeTypeHandler());
    register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
    try {
        register("java.time.Instant", "org.apache.ibatis.type.InstantTypeHandler");
        register("java.time.LocalDateTime", "org.apache.ibatis.type.LocalDateTimeTypeHandler");
        register("java.time.LocalDate", "org.apache.ibatis.type.LocalDateTypeHandler");
        register("java.time.LocalTime", "org.apache.ibatis.type.LocalTimeTypeHandler");
        register("java.time.OffsetDateTime", "org.apache.ibatis.type.OffsetDateTimeTypeHandler");
        register("java.time.OffsetTime", "org.apache.ibatis.type.OffsetTimeTypeHandler");
        register("java.time.ZonedDateTime", "org.apache.ibatis.type.ZonedDateTimeTypeHandler");
        register("java.time.Month", "org.apache.ibatis.type.MonthTypeHandler");
        register("java.time.Year", "org.apache.ibatis.type.YearTypeHandler");
        register("java.time.YearMonth", "org.apache.ibatis.type.YearMonthTypeHandler");
        register("java.time.chrono.JapaneseDate", "org.apache.ibatis.type.JapaneseDateTypeHandler");
    } catch (ClassNotFoundException e) {
    }
    register(Character.class, new CharacterTypeHandler());
    register(char.class, new CharacterTypeHandler());
}

配置文件解析的最后一步就是对mapper配置的解析:
XMLConfigBuilder:

private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
        for (XNode child : parent.getChildren()) {
            if ("package".equals(child.getName())) {
                String mapperPackage = child.getStringAttribute("name");
                /* 按照包名配置解析 */
                configuration.addMappers(mapperPackage);
            } else {
                String resource = child.getStringAttribute("resource");
                String url = child.getStringAttribute("url");
                String mapperClass = child.getStringAttribute("class");
                if (resource != null && url == null && mapperClass == null) {
                    ErrorContext.instance().resource(resource);
                    InputStream inputStream = Resources.getResourceAsStream(resource);
                    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
                    /* 按照resource配置解析 */
                    mapperParser.parse();
                } else if (resource == null && url != null && mapperClass == null) {
                    ErrorContext.instance().resource(url);
                    InputStream inputStream = Resources.getUrlAsStream(url);
                    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
                    /* 按照url配置解析 */
                    mapperParser.parse();
                } else if (resource == null && url == null && mapperClass != null) {
                    Class<?> mapperInterface = Resources.classForName(mapperClass);
                    /* 按照class配置解析 */
                    configuration.addMapper(mapperInterface);
                } else {
                    // 三者只能出现一个,某则抛出异常
                    throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
                }
            }
        }
    }
}

Configuration:

public void addMappers(String packageName) {
    /* 根据包名注册mapper */
    mapperRegistry.addMappers(packageName);
}

MapperRegistry:

public void addMappers(String packageName, Class<?> superType) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    // 加载包下面的类
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
    for (Class<?> mapperClass : mapperSet) {
        /* 添加mapper */
        addMapper(mapperClass);
    }
}

MapperRegistry:

public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) { // mapper类必须是接口
        if (hasMapper(type)) { // 如果mapper已经存在,报错
            throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
        }
        boolean loadCompleted = false;
        try {
            knownMappers.put(type, new MapperProxyFactory<T>(type)); // 将当前mapper添加到已知mapper集合中
            MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
            parser.parse(); /* 解析mapper配置 */
            loadCompleted = true;
        } finally {
            if (!loadCompleted) {
                knownMappers.remove(type); // 如果解析出现异常,从已知的mapper集合中移除掉当前mapper
            }
        }
    }
}

MapperAnnotationBuilder:

public void parse() {
    String resource = type.toString();
    // 判断是否已经加载过,防止重复加载
    if (!configuration.isResourceLoaded(resource)) {
        loadXmlResource(); /* 加载xml配置 */
        configuration.addLoadedResource(resource); // 标记为已经加载的资源
        assistant.setCurrentNamespace(type.getName());
        parseCache(); /* 解析@CacheNamespace注解配置 */
        parseCacheRef(); /* 解析@CacheNamespaceRef注解配置 */
        Method[] methods = type.getMethods();
        for (Method method : methods) {
            try {
                if (!method.isBridge()) {
                    parseStatement(method); /* 解析方法上的注解配置 */
                }
            } catch (IncompleteElementException e) {
                // 添加到未完成解析的方法解析器集合中,后续继续解析
                configuration.addIncompleteMethod(new MethodResolver(this, method));
            }
        }
    }
    parsePendingMethods(); // 解析挂起的方法
}

MapperAnnotationBuilder:

private void loadXmlResource() {
    // 判断是否已经加载过,防止重复加载
    if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
        // 将类名的.替换成/,也就是查找当前路径下同名的xml文件作为配置文件
        String xmlResource = type.getName().replace('.', '/') + ".xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
        } catch (IOException e) {
        }
        if (inputStream != null) {
            XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
            /* 解析xml配置 */
            xmlParser.parse();
        }
    }
}
public void parse() {
    // 判断是否已经加载过,防止重复加载
    if (!configuration.isResourceLoaded(resource)) {
        /* 解析mapper配置 */
        configurationElement(parser.evalNode("/mapper"));
        configuration.addLoadedResource(resource); // 标记为已加载资源
        bindMapperForNamespace(); /* 为命名空间绑定mapper */
    }
    parsePendingResultMaps(); // 解析挂起的resultMap
    parsePendingCacheRefs(); // 解析挂起的cacheRef
    parsePendingStatements(); // 解析挂起的statement
}

这里提到了对挂起元素的解析,什么时候会有挂起元素后面会详细说明,对挂起元素的解析和正常解析的流程是一样的,就是从configuration对象中拿出挂起的元素再次解析一遍。
XMLMapperBuilder:

private void configurationElement(XNode context) {
    try {
        String namespace = context.getStringAttribute("namespace"); // 获取命名空间配置
        if (namespace == null || namespace.equals("")) {
            throw new BuilderException("Mapper's namespace cannot be empty");
        }
        // 设置当前命名空间
        builderAssistant.setCurrentNamespace(namespace);
        /* 标签解析 */
        cacheRefElement(context.evalNode("cache-ref"));
        /* 标签解析 */
        cacheElement(context.evalNode("cache"));
        // 标签解析,目前已经废弃这个用法
        parameterMapElement(context.evalNodes("/mapper/parameterMap"));
        /* 标签解析 */
        resultMapElements(context.evalNodes("/mapper/resultMap"));
        /* 标签解析 */
        sqlElement(context.evalNodes("/mapper/sql"));
        /* 四个标签的解析:
XMLMapperBuilder:

private void buildStatementFromContext(List<XNode> list) {
    if (configuration.getDatabaseId() != null) {
        /* 解析,携带databaseId配置 */
        buildStatementFromContext(list, configuration.getDatabaseId());
    }
    /* 解析,不带databaseId配置 */
    buildStatementFromContext(list, null);
}

XMLMapperBuilder:

private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
    for (XNode context : list) {
        final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
        try {
            /* 解析 */
            statementParser.parseStatementNode();
        } catch (IncompleteElementException e) {
            // 添加到未完成解析statement元素集合中,后续继续解析
            configuration.addIncompleteStatement(statementParser);
        }
    }
}

XMLStatementBuilder:

public void parseStatementNode() {
    // 提取id配置
    String id = context.getStringAttribute("id");
    // 提取databaseId配置
    String databaseId = context.getStringAttribute("databaseId");
    // 判断是否匹配,上面分析过
    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
        return;
    }
    // 各个属性的提取
    Integer fetchSize = context.getIntAttribute("fetchSize");
    Integer timeout = context.getIntAttribute("timeout");
    String parameterMap = context.getStringAttribute("parameterMap");
    String parameterType = context.getStringAttribute("parameterType");
    // 获取parameterType配置的类名或类别名对应的Class对象
    Class<?> parameterTypeClass = resolveClass(parameterType);
    String resultMap = context.getStringAttribute("resultMap");
    String resultType = context.getStringAttribute("resultType");
    String lang = context.getStringAttribute("lang");
    // 获取lang配置对应的语言驱动,在构造Configuration对象时,Mybatis注册了XMLLanguageDriver、RawLanguageDriver两个语言驱动,并将XMLLanguageDriver设置为默认的语言驱动
    LanguageDriver langDriver = getLanguageDriver(lang);
    // 获取resultType配置的类名或类别名对应的Class对象
    Class<?> resultTypeClass = resolveClass(resultType);
    String resultSetType = context.getStringAttribute("resultSetType");
    // 根据statementType配置的名称在枚举找到对应的枚举值,默认为PREPARED
    StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    // 根据resultSetType配置的名称在枚举找到对应的枚举值
    ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
    String nodeName = context.getNode().getNodeName();
    // 根据标签的名称在SqlCommandType枚举中找到对应的枚举值,如标签默认为false,其他为true
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    // 提取useCache配置,,就遍历子节点递归此方法
            applyIncludes(children.item(i), variablesContext, included);
        }
    } else if (included && source.getNodeType() == Node.TEXT_NODE
        && !variablesContext.isEmpty()) {
        // 如果是文本类型的Node,则解析并设置节点值,主要是替换节点值中声明的变量如${var1}
        source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));
    }
}

XMLIncludeTransformer:

private Node findSqlFragment(String refid, Properties variables) {
    // 解析refid中声明的变量,如${var1}
    refid = PropertyParser.parse(refid, variables);
    // 应用当前命名空间,命名空间+refid
    refid = builderAssistant.applyCurrentNamespace(refid, true);
    try {
        // 根据refid从之前解析标签时添加的映射中获取对应的节点
        XNode nodeToInclude = configuration.getSqlFragments().get(refid);
        // 复制一份返回
        return nodeToInclude.getNode().cloneNode(true);
    } catch (IllegalArgumentException e) {
        throw new IncompleteElementException("Could not find SQL statement to include with refid '" + refid + "'", e);
    }
}

XMLIncludeTransformer:

private Properties getVariablesContext(Node node, Properties inheritedVariablesContext) {
    Map<String, String> declaredProperties = null;
    NodeList children = node.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
        Node n = children.item(i); // 子节点也就是标签
        if (n.getNodeType() == Node.ELEMENT_NODE) {
            // 提取name属性
            String name = getStringAttribute(n, "name");
            // 提取value属性,并解析属性值中声明的变量
            String value = PropertyParser.parse(getStringAttribute(n, "value"), inheritedVariablesContext);
            if (declaredProperties == null) {
                declaredProperties = new HashMap<String, String>();
            }
            // 添加到声明的属性映射中
            if (declaredProperties.put(name, value) != null) {
                // 重复声明抛异常
                throw new BuilderException("Variable " + name + " defined twice in the same include definition");
            }
        }
    }
    if (declaredProperties == null) {
        // 声明属性为空直接返回继承的全局变量
        return inheritedVariablesContext;
    } else {
        // 声明属性不为空则将两者放入新的Properties对象中返回
        Properties newProperties = new Properties();
        newProperties.putAll(inheritedVariablesContext);
        newProperties.putAll(declaredProperties);
        return newProperties;
    }
}

下面是标签的解析
XMLStatementBuilder:

private void processSelectKeyNodes(String id, Class<?> parameterTypeClass, LanguageDriver langDriver) {
    List<XNode> selectKeyNodes = context.evalNodes("selectKey");
    if (configuration.getDatabaseId() != null) {
        /* 解析selectKey节点,携带databaseId配置 */
        parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, configuration.getDatabaseId());
    }
    /* 解析selectKey节点,不带databaseId配置 */
    parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, null);
    // 解析完成之后从父节点中移除掉
    removeSelectKeyNodes(selectKeyNodes);
}

XMLStatementBuilder:

private void parseSelectKeyNodes(String parentId, List<XNode> list, Class<?> parameterTypeClass, LanguageDriver langDriver, String skRequiredDatabaseId) {
    for (XNode nodeToHandle : list) {
        // 设置id为父节点的id属性加上!selectKey后缀
        String id = parentId + SelectKeyGenerator.SELECT_KEY_SUFFIX;
        String databaseId = nodeToHandle.getStringAttribute("databaseId");
        // 判断databaseId配置是否匹配,上文分析过
        if (databaseIdMatchesCurrent(id, databaseId, skRequiredDatabaseId)) {
            /* 解析selectKey节点 */
            parseSelectKeyNode(id, nodeToHandle, parameterTypeClass, langDriver, databaseId);
        }
    }
}

XMLStatementBuilder:

private void parseSelectKeyNode(String id, XNode nodeToHandle, Class<?> parameterTypeClass, LanguageDriver langDriver, String databaseId) {
    // 各个属性的提取
    String resultType = nodeToHandle.getStringAttribute("resultType");
    // 解析resultType对应的类名或类别名
    Class<?> resultTypeClass = resolveClass(resultType);
    StatementType statementType = StatementType.valueOf(nodeToHandle.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    String keyProperty = nodeToHandle.getStringAttribute("keyProperty");
    String keyColumn = nodeToHandle.getStringAttribute("keyColumn");
    boolean executeBefore = "BEFORE".equals(nodeToHandle.getStringAttribute("order", "AFTER"));
    // 一些默认值的声明
    boolean useCache = false;
    boolean resultOrdered = false;
    KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
    Integer fetchSize = null;
    Integer timeout = null;
    boolean flushCache = false;
    String parameterMap = null;
    String resultMap = null;
    ResultSetType resultSetTypeEnum = null;
    /* 创建SqlSource */
    SqlSource sqlSource = langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass);
    SqlCommandType sqlCommandType = SqlCommandType.SELECT;
    /* 添加MappedStatement */
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered,
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, null);
    // 应用当前命名空间,命名空间+id
    id = builderAssistant.applyCurrentNamespace(id, false);
    MappedStatement keyStatement = configuration.getMappedStatement(id, false);
    // 添加SelectKeyGenerator,在sql执行前后为参数赋相应的值
    configuration.addKeyGenerator(id, new SelectKeyGenerator(keyStatement, executeBefore));
}

XMLLanguageDriver:

 public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
     XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
     /* 解析节点,创建SqlSource */
     return builder.parseScriptNode();
 }

XMLScriptBuilder:

public SqlSource parseScriptNode() {
    /* 解析动态标签 */
    List<SqlNode> contents = parseDynamicTags(context);
    MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
    SqlSource sqlSource = null;
    // 根据解析时判断的是否是动态标签的结果来创建不同的SqlSource
    if (isDynamic) {
        sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
    } else {
        sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
    }
    return sqlSource;
}

XMLScriptBuilder:

List<SqlNode> parseDynamicTags(XNode node) {
    List<SqlNode> contents = new ArrayList<SqlNode>();
    NodeList children = node.getNode().getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
        XNode child = node.newXNode(children.item(i));
        if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
            String data = child.getStringBody("");
            TextSqlNode textSqlNode = new TextSqlNode(data);
            /* 判断文本类型的node是否是动态的 */
            if (textSqlNode.isDynamic()) {
                contents.add(textSqlNode);
                isDynamic = true;
            } else {
                contents.add(new StaticTextSqlNode(data));
            }
      } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) {
          String nodeName = child.getNode().getNodeName();
          /* 获取动态节点的处理器 */
          NodeHandler handler = nodeHandlers(nodeName);
          if (handler == null) {
              throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
          }
          /* 处理动态节点 */
          handler.handleNode(child, contents);
          isDynamic = true;
      }
  }
  return contents;
}

TextSqlNode:

public boolean isDynamic() {
    DynamicCheckerTokenParser checker = new DynamicCheckerTokenParser();
    /* 创建解析器 */
    GenericTokenParser parser = createParser(checker);
    /* 解析 */
    parser.parse(text);
    return checker.isDynamic();
}

TextSqlNode:

private GenericTokenParser createParser(TokenHandler handler) {
    return new GenericTokenParser("${", "}", handler);
}

GenericTokenParser:

public String parse(String text) {
    if (text == null || text.isEmpty()) {
        return ""; // 文本为空返回空字符串
    }
    char[] src = text.toCharArray();
    int offset = 0;
    // openToken:${,closeToken:}
    int start = text.indexOf(openToken, offset);
    if (start == -1) {
        return text; // openToken在文本中不存在,返回文本
    }
    final StringBuilder builder = new StringBuilder();
    StringBuilder expression = null;
    while (start > -1) {
        // 如果openToken前面是反斜杠\转义字符,移除掉并继续
        if (start > 0 && src[start - 1] == '\\') {
            builder.append(src, offset, start - offset - 1).append(openToken);
            offset = start + openToken.length();
        } else {
            // 找到了openToken,下面要找closeToken
            if (expression == null) {
                expression = new StringBuilder();
            } else {
                expression.setLength(0);
            }
            builder.append(src, offset, start - offset);
            offset = start + openToken.length();
            int end = text.indexOf(closeToken, offset);
            while (end > -1) {
                if (end > offset && src[end - 1] == '\\') {
                    // 同样的,如果closeToken前面是反斜杠\转义字符,移除掉并继续
                    expression.append(src, offset, end - offset - 1).append(closeToken);
                    offset = end + closeToken.length();
                    end = text.indexOf(closeToken, offset);
                } else {
                    expression.append(src, offset, end - offset);
                    offset = end + closeToken.length();
                    break;
                }
            }
            if (end == -1) {
                // closeToken没有找到的情况
                builder.append(src, start, src.length - start);
                offset = src.length;
            } else {
                /* 处理表达式 */
                builder.append(handler.handleToken(expression.toString()));
                offset = end + closeToken.length();
            }
        }
        start = text.indexOf(openToken, offset);
    }
    if (offset < src.length) {
        builder.append(src, offset, src.length - offset);
    }
    return builder.toString();
}

TextSqlNode.DynamicCheckerTokenParser:

public String handleToken(String content) {
    this.isDynamic = true; // 将动态标记设置为true
    return null;
}

XMLScriptBuilder:

NodeHandler nodeHandlers(String nodeName) {
    Map<String, NodeHandler> map = new HashMap<String, NodeHandler>();
    map.put("trim", new TrimHandler());
    map.put("where", new WhereHandler());
    map.put("set", new SetHandler());
    map.put("foreach", new ForEachHandler());
    map.put("if", new IfHandler());
    map.put("choose", new ChooseHandler());
    map.put("when", new IfHandler());
    map.put("otherwise", new OtherwiseHandler());
    map.put("bind", new BindHandler());
    return map.get(nodeName);
}

这里我们看到了Mybatis提供的一些动态标签的处理器,如等,我们以标签为例来看它如何处理动态标签,而处理过后节点的应用则是在mapper方法执行的过程中,我们会在后续的文章中进行详细讲解,其他动态标签的处理也是类似的:
XMLScriptBuilder.IfHandler:

public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
    // 递归解析当前节点的动态子节点
    List<SqlNode> contents = parseDynamicTags(nodeToHandle);
    MixedSqlNode mixedSqlNode = new MixedSqlNode(contents);
    // 提取标签test属性配置
    String test = nodeToHandle.getStringAttribute("test");
    // 构建相关Node节点
    IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test);
    targetContents.add(ifSqlNode);
}

解析标签最后是构建并添加MappedStatement:
MapperBuilderAssistant:

public MappedStatement addMappedStatement(
    String id,
    SqlSource sqlSource,
    StatementType statementType,
    SqlCommandType sqlCommandType,
    Integer fetchSize,
    Integer timeout,
    String parameterMap,
    Class<?> parameterType,
    String resultMap,
    Class<?> resultType,
    ResultSetType resultSetType,
    boolean flushCache,
    boolean useCache,
    boolean resultOrdered,
    KeyGenerator keyGenerator,
    String keyProperty,
    String keyColumn,
    String databaseId,
    LanguageDriver lang,
    String resultSets) {
    if (unresolvedCacheRef) {
        throw new IncompleteElementException("Cache-ref not yet resolved");
    }
    // 应用当前命名空间,命名空间+id
    id = applyCurrentNamespace(id, false);
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    // 将各个解析好的属性复制给MappedStatement.Builder对象中的MappedStatement实例的各个属性
    MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
        .resource(resource)
        .fetchSize(fetchSize)
        .timeout(timeout)
        .statementType(statementType)
        .keyGenerator(keyGenerator)
        .keyProperty(keyProperty)
        .keyColumn(keyColumn)
        .databaseId(databaseId)
        .lang(lang)
        .resultOrdered(resultOrdered)
        .resultSets(resultSets)
        .resultMaps(getStatementResultMaps(resultMap, resultType, id))
        .resultSetType(resultSetType)
        .flushCacheRequired(valueOrDefault(flushCache, !isSelect))
        .useCache(valueOrDefault(useCache, isSelect))
        .cache(currentCache);
    /* 获取参数映射 */
    ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
    if (statementParameterMap != null) {
        statementBuilder.parameterMap(statementParameterMap);
    }
    // 返回MappedStatement对象
    MappedStatement statement = statementBuilder.build();
    // 添加到configuration对象中
    configuration.addMappedStatement(statement);
    return statement;
}

MapperBuilderAssistant:

private ParameterMap getStatementParameterMap(
    String parameterMapName,
    Class<?> parameterTypeClass,
    String statementId) {
    parameterMapName = applyCurrentNamespace(parameterMapName, true);
    ParameterMap parameterMap = null;
    // parameterMap已经不推荐使用
    if (parameterMapName != null) {
        try {
            parameterMap = configuration.getParameterMap(parameterMapName);
        } catch (IllegalArgumentException e) {
            throw new IncompleteElementException("Could not find parameter map " + parameterMapName, e);
        }
    } else if (parameterTypeClass != null) {
        List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
        // paramType方式的配置,构建ParameterMap对象
        parameterMap = new ParameterMap.Builder(
            configuration,
            statementId + "-Inline",
            parameterTypeClass,
            parameterMappings).build();
    }
    return parameterMap;
}

标签解析完成了,下面会继续