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);
        /* <cache-ref/>标签解析 */
        cacheRefElement(context.evalNode("cache-ref"));
        /* <cache/>标签解析 */
        cacheElement(context.evalNode("cache"));
        // <parameterMap/>标签解析,目前已经废弃这个用法
        parameterMapElement(context.evalNodes("/mapper/parameterMap"));
        /* <resultMap/>标签解析 */
        resultMapElements(context.evalNodes("/mapper/resultMap"));
        /* <sql/>标签解析 */
        sqlElement(context.evalNodes("/mapper/sql"));
        /* <select/>、<insert/>、<update/>、<delete/>标签解析 */
        buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
        throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
    }
}

XMLMapperBuilder:

private void cacheRefElement(XNode context) {
    if (context != null) {
        // 将当前命名空间和cache-ref中配置的命名空间添加映射关系
        configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
        CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
        try {
            // 这里的解析主要是验证cache-ref关联的缓存对象是否已经存在,如果不存在,就会抛出IncompleteElementException异常
            cacheRefResolver.resolveCacheRef();
        } catch (IncompleteElementException e) {
            // 添加到未完成解析的cache-ref集合中,后续继续解析
            configuration.addIncompleteCacheRef(cacheRefResolver);
        }
    }
}

XMLMapperBuilder:

private void cacheElement(XNode context) throws Exception {
    if (context != null) {
        // 获取缓存类型配置,默认为PERPETUAL持久化缓存,支持实现Cache接口自定义缓存
        String type = context.getStringAttribute("type", "PERPETUAL");
        // 获取类名或类别名对应的Class对象
        Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
        // 获取回收策略配置,默认为LRU最近最少使用原则
        String eviction = context.getStringAttribute("eviction", "LRU");
        // 获取类名或类别名对应的Class对象,Mybatis提供的几种的回收策略在构建Configuration对象时注册了别名,上文介绍过
        Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
        // 获取flushInterval缓存刷新间隔配置,默认没有刷新间隔
        Long flushInterval = context.getLongAttribute("flushInterval");
        // 获取size缓存引用数目配置,默认值是1024
        Integer size = context.getIntAttribute("size");
        // 获取缓存只读属性配置
        boolean readWrite = !context.getBooleanAttribute("readOnly", false);
        // 获取缓存blocking配置
        boolean blocking = context.getBooleanAttribute("blocking", false);
        // 将子标签的name和value属性作为键值对放入Properties对象中
        Properties props = context.getChildrenAsProperties();
        /* 添加缓存 */
        builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
    }
}

MapperBuilderAssistant:

public Cache useNewCache(Class<? extends Cache> typeClass,
    Class<? extends Cache> evictionClass,
    Long flushInterval,
    Integer size,
    boolean readWrite,
    boolean blocking,
    Properties props) {
    /* 构建缓存 */
    Cache cache = new CacheBuilder(currentNamespace)
        .implementation(valueOrDefault(typeClass, PerpetualCache.class))
        .addDecorator(valueOrDefault(evictionClass, LruCache.class))
        .clearInterval(flushInterval)
        .size(size)
        .readWrite(readWrite)
        .blocking(blocking)
        .properties(props)
        .build();
    // 添加到缓存映射中
    configuration.addCache(cache);
    currentCache = cache;
    return cache;
}

CacheBuilder:

public Cache build() {
    // 设置默认实现,如果没有默认实现会用PerpetualCache作为默认实现并添加默认装饰者LruCache
    setDefaultImplementations();
    // 反射实例化cache,id也就是命名空间会作为构造方法的参数
    Cache cache = newBaseCacheInstance(implementation, id);
    /* 为缓存设置用户自定义属性 */
    setCacheProperties(cache);
    if (PerpetualCache.class.equals(cache.getClass())) {
        for (Class<? extends Cache> decorator : decorators) {
            // 装饰者装饰缓存对象,默认就是LruCache装饰PerpetualCache
            cache = newCacheDecoratorInstance(decorator, cache);
            /* 装饰者装饰之后再次为缓存对象设置用户自定义属性 */
            setCacheProperties(cache);
        }
        /* 设置基本的装饰者 */
        cache = setStandardDecorators(cache);
    } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
        // 如果基本cache对象不是PerpetualCache并且没有继承LoggingCache,那么用LoggingCache装饰基本cache对象,主要是为了记录缓存命中比例
        cache = new LoggingCache(cache);
    }
    return cache;
}

CacheBuilder:

private void setCacheProperties(Cache cache) {
    if (properties != null) {
        MetaObject metaCache = SystemMetaObject.forObject(cache);
        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
            String name = (String) entry.getKey();
            String value = (String) entry.getValue();
            // 根据配置找到相关setter方法调用赋值
            if (metaCache.hasSetter(name)) {
                Class<?> type = metaCache.getSetterType(name);
                if (String.class == type) {
                    metaCache.setValue(name, value);
                } else if (int.class == type
                    || Integer.class == type) {
                    metaCache.setValue(name, Integer.valueOf(value));
                } else if (long.class == type
                    || Long.class == type) {
                    metaCache.setValue(name, Long.valueOf(value));
                } else if (short.class == type
                    || Short.class == type) {
                    metaCache.setValue(name, Short.valueOf(value));
                } else if (byte.class == type
                    || Byte.class == type) {
                    metaCache.setValue(name, Byte.valueOf(value));
                } else if (float.class == type
                    || Float.class == type) {
                    metaCache.setValue(name, Float.valueOf(value));
                } else if (boolean.class == type
                    || Boolean.class == type) {
                    metaCache.setValue(name, Boolean.valueOf(value));
                } else if (double.class == type
                    || Double.class == type) {
                    metaCache.setValue(name, Double.valueOf(value));
                } else {
                    throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type);
                }
            }
        }
    }
    // 如果cache对象实现了InitializingObject接口,在这里调用它的initialize方法
    if (InitializingObject.class.isAssignableFrom(cache.getClass())){
        try {
            ((InitializingObject) cache).initialize();
        } catch (Exception e) {
            throw new CacheException("Failed cache initialization for '" +
                cache.getId() + "' on '" + cache.getClass().getName() + "'", e);
        }
    }
}

CacheBuilder:

private Cache setStandardDecorators(Cache cache) {
    try {
        MetaObject metaCache = SystemMetaObject.forObject(cache);
        if (size != null && metaCache.hasSetter("size")) {
            metaCache.setValue("size", size);
        }
        if (clearInterval != null) {
            // 如果配置了flushInterval,则用ScheduledCache装饰基本cache对象
            cache = new ScheduledCache(cache);
            ((ScheduledCache) cache).setClearInterval(clearInterval);
        }
        if (readWrite) {
            // 如果配置了readOnly为true,则用SerializedCache装饰基本cache对象
            cache = new SerializedCache(cache);
        }
        // 用LoggingCache装饰基本cache对象
        cache = new LoggingCache(cache);
        // 用SynchronizedCache装饰基本cache对象
        cache = new SynchronizedCache(cache);
        // 如果配置了blocking为true,则用BlockingCache装饰基本cache对象
        if (blocking) {
            cache = new BlockingCache(cache);
        }
        return cache;
    } catch (Exception e) {
        throw new CacheException("Error building standard cache decorators.  Cause: " + e, e);
    }
}

XMLMapperBuilder:

private void resultMapElements(List<XNode> list) throws Exception {
    for (XNode resultMapNode : list) {
        try {
            /* 解析<resultMap/>标签 */
            resultMapElement(resultMapNode);
        } catch (IncompleteElementException e) {
        }
    }
}

XMLMapperBuilder:

private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
    /* 解析<resultMap/>标签 */
    return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList());
}

XMLMapperBuilder:

private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
    ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
    // 提取id属性
    String id = resultMapNode.getStringAttribute("id",
        resultMapNode.getValueBasedIdentifier());
    // 按优先级提取type属性
    String type = resultMapNode.getStringAttribute("type",
        resultMapNode.getStringAttribute("ofType",
            resultMapNode.getStringAttribute("resultType",
                resultMapNode.getStringAttribute("javaType"))));
    // 提取extends配置
    String extend = resultMapNode.getStringAttribute("extends");
    // 提取autoMapping配置
    Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
    Class<?> typeClass = resolveClass(type);
    Discriminator discriminator = null;
    List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
    resultMappings.addAll(additionalResultMappings);
    List<XNode> resultChildren = resultMapNode.getChildren();
    for (XNode resultChild : resultChildren) {
        if ("constructor".equals(resultChild.getName())) {
            /* 处理<constructor/>子标签 */
            processConstructorElement(resultChild, typeClass, resultMappings);
        } else if ("discriminator".equals(resultChild.getName())) {
            /* 处理<discriminator/>子标签 */
            discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
        } else {
            List<ResultFlag> flags = new ArrayList<ResultFlag>();
            if ("id".equals(resultChild.getName())) {
                // 如果是<id/>子标签,添加标记
                flags.add(ResultFlag.ID);
            }
            /* 构建ResultMapping */
            resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
        }
    }
    ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
    try {
        /* 解析返回ResultMap */
        return resultMapResolver.resolve();
    } catch (IncompleteElementException  e) {
        // 添加到未完成解析的ResultMap集合中,后续继续解析
        configuration.addIncompleteResultMap(resultMapResolver);
        throw e;
    }
}

XMLMapperBuilder:

private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
    List<XNode> argChildren = resultChild.getChildren();
    for (XNode argChild : argChildren) {
        List<ResultFlag> flags = new ArrayList<ResultFlag>();
        flags.add(ResultFlag.CONSTRUCTOR);
        if ("idArg".equals(argChild.getName())) {
            // 如果子标签是<idArg/>添加标记
            flags.add(ResultFlag.ID);
        }
        /* 构建并添加ResultMapping */
        resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
    }
}

XMLMapperBuilder:

private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception {
    String property; // 提取属性,<constructor/>提取name,其他标签提取property
    if (flags.contains(ResultFlag.CONSTRUCTOR)) {
        property = context.getStringAttribute("name");
    } else {
        property = context.getStringAttribute("property");
    }
    // 下面是各种标签属性的提取
    String column = context.getStringAttribute("column");
    String javaType = context.getStringAttribute("javaType");
    String jdbcType = context.getStringAttribute("jdbcType");
    String nestedSelect = context.getStringAttribute("select");
    /* 递归处理嵌套的resultMapping */
    String nestedResultMap = context.getStringAttribute("resultMap",
        processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));
    String notNullColumn = context.getStringAttribute("notNullColumn");
    String columnPrefix = context.getStringAttribute("columnPrefix");
    String typeHandler = context.getStringAttribute("typeHandler");
    String resultSet = context.getStringAttribute("resultSet");
    String foreignColumn = context.getStringAttribute("foreignColumn");
    boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
    // 获取javaType配置的类名或类别名对应的Class对象
    Class<?> javaTypeClass = resolveClass(javaType);
    @SuppressWarnings("unchecked")
    // 获取typeHandler配置的类名或类别名对应的Class对象
    Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
    // 根据jdbcType配置的名称在枚举找到对应的枚举值
    JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
    /* 构建ResultMapping */
    return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy);
}

XMLMapperBuilder:

private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings) throws Exception {
    if ("association".equals(context.getName())
        || "collection".equals(context.getName())
        || "case".equals(context.getName())) {
        if (context.getStringAttribute("select") == null) {
            // 如果是<association/>、<collection/>、<case/>三个标签中的一个并且没有配置select属性,则递归解析成ResultMap对象
            ResultMap resultMap = resultMapElement(context, resultMappings);
            return resultMap.getId();
        }
    }
    return null;
}

MapperBuilderAssistant:

public ResultMapping buildResultMapping(
    Class<?> resultType,
    String property,
    String column,
    Class<?> javaType,
    JdbcType jdbcType,
    String nestedSelect,
    String nestedResultMap,
    String notNullColumn,
    String columnPrefix,
    Class<? extends TypeHandler<?>> typeHandler,
    List<ResultFlag> flags,
    String resultSet,
    String foreignColumn,
    boolean lazy) {
    // 如果配置了javaType则返回javaType对应的Class对象,如果没有配置,则根据父标签配置的类型的相关property属性的相关setter方法的参数类型当做javaType返回
    Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
    // 从TypeHandler映射中获取对应的TypeHandler,如果获取不到,则通过javaTypeClass和typeHandlerClass实例化TypeHandler
    TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
    /* 解析组合的column属性 */
    List<ResultMapping> composites = parseCompositeColumnName(column);
    // 将解析后的每个属性封装到ResultMapping对象中返回
    return new ResultMapping.Builder(configuration, property, column, javaTypeClass)
        .jdbcType(jdbcType)
        .nestedQueryId(applyCurrentNamespace(nestedSelect, true))
        .nestedResultMapId(applyCurrentNamespace(nestedResultMap, true))
        .resultSet(resultSet)
        .typeHandler(typeHandlerInstance)
        .flags(flags == null ? new ArrayList<ResultFlag>() : flags)
        .composites(composites)
        .notNullColumns(parseMultipleColumnNames(notNullColumn))
        .columnPrefix(columnPrefix)
        .foreignColumn(foreignColumn)
        .lazy(lazy)
        .build();
}

MapperBuilderAssistant:

private List<ResultMapping> parseCompositeColumnName(String columnName) {
    List<ResultMapping> composites = new ArrayList<ResultMapping>();
    // column属性可以这样配置:column="{prop1=col1,prop2=col2}"
    if (columnName != null && (columnName.indexOf('=') > -1 || columnName.indexOf(',') > -1)) {
        StringTokenizer parser = new StringTokenizer(columnName, "{}=, ", false);
        while (parser.hasMoreTokens()) {
            String property = parser.nextToken(); // prop1
            String column = parser.nextToken(); // col1
            // 将解析后的属性封装到ResultMapping对象中
            ResultMapping complexResultMapping = new ResultMapping.Builder(
                configuration, property, column, configuration.getTypeHandlerRegistry().getUnknownTypeHandler()).build();
            composites.add(complexResultMapping);
        }
    }
    return composites;
}

下面我们来看<discriminator/>子标签的解析:
XMLMapperBuilder:

private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
    // 各个属性的提取
    String column = context.getStringAttribute("column");
    String javaType = context.getStringAttribute("javaType");
    String jdbcType = context.getStringAttribute("jdbcType");
    String typeHandler = context.getStringAttribute("typeHandler");
    // 获取javaType配置的类名或类别名对应的Class对象
    Class<?> javaTypeClass = resolveClass(javaType);
    // 获取typeHandler配置的类名或类别名对应的Class对象
    @SuppressWarnings("unchecked")
    Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
    // 根据jdbcType配置的名称在枚举找到对应的枚举值
    JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
    Map<String, String> discriminatorMap = new HashMap<String, String>();
    // <case/>子标签
    for (XNode caseChild : context.getChildren()) {
        // 提取value属性
        String value = caseChild.getStringAttribute("value");
        // 提取resultMap属性,递归处理嵌套的resultMapping,上面已经分析过
        String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings));
        discriminatorMap.put(value, resultMap);
    }
    /* 构建鉴别器 */
    return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap);
}

MapperBuilderAssistant:

public Discriminator buildDiscriminator(
    Class<?> resultType,
    String column,
    Class<?> javaType,
    JdbcType jdbcType,
    Class<? extends TypeHandler<?>> typeHandler,
    Map<String, String> discriminatorMap) {
    // 构建ResultMapping
    ResultMapping resultMapping = buildResultMapping(
        resultType,
        null,
        column,
        javaType,
        jdbcType,
        null,
        null,
        null,
        null,
        typeHandler,
        new ArrayList<ResultFlag>(),
        null,
        null,
        false);
    Map<String, String> namespaceDiscriminatorMap = new HashMap<String, String>();
    for (Map.Entry<String, String> e : discriminatorMap.entrySet()) {
        String resultMap = e.getValue();
        // 应用当前命名空间,命名空间+resultMap的id
        resultMap = applyCurrentNamespace(resultMap, true);
        namespaceDiscriminatorMap.put(e.getKey(), resultMap);
    }
    // 将解析好的属性封装到Discriminator对象中构建鉴别器
    return new Discriminator.Builder(configuration, resultMapping, namespaceDiscriminatorMap).build();
}

接下来就是构建并返回ResultMap对象了:

public ResultMap resolve() {
    /* 将resultMap添加到configuration对象中并返回 */
    return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping);
}

MapperBuilderAssistant:

public ResultMap addResultMap(
    String id,
    Class<?> type,
    String extend,
    Discriminator discriminator,
    List<ResultMapping> resultMappings,
    Boolean autoMapping) {
    // 分别对id和extend应用当前命名空间,命名空间+resultMap的id
    id = applyCurrentNamespace(id, false);
    extend = applyCurrentNamespace(extend, true);
    if (extend != null) {
        // 如果configuration对象中不包含extend对应的resultMap,抛出IncompleteElementException,添加到未完成解析的ResultMap集合中,后续继续解析
        if (!configuration.hasResultMap(extend)) {
            throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'");
        }
        // 获取configuration对象中extend对应的resultMap
        ResultMap resultMap = configuration.getResultMap(extend);
        // 复制一份extend对应的resultMap中的resultMapping
        List<ResultMapping> extendedResultMappings = new ArrayList<ResultMapping>(resultMap.getResultMappings());
        // 移除掉与当前resultMap中相同的resultMapping
        extendedResultMappings.removeAll(resultMappings);
        boolean declaresConstructor = false;
        for (ResultMapping resultMapping : resultMappings) {
            // 如果有CONSTRUCTOR标记也就是包含<constructor/>标签,做一个标记
            if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {
                declaresConstructor = true;
                break;
            }
        }
        // 如果当前resultMap中配置了<constructor/>标签,则溢出extend对应的resultMap中标记为CONSTRUCTOR的resultMapping
        if (declaresConstructor) {
            Iterator<ResultMapping> extendedResultMappingsIter = extendedResultMappings.iterator();
            while (extendedResultMappingsIter.hasNext()) {
                if (extendedResultMappingsIter.next().getFlags().contains(ResultFlag.CONSTRUCTOR)) {
                    extendedResultMappingsIter.remove();
                }
            }
        }
        // 将extend对应的resultMapping添加到当前resultMapping集合中
        resultMappings.addAll(extendedResultMappings);
    }
    // 将解析好的各个属性封装到ResultMap对象中返回
    ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping)
    .discriminator(discriminator)
    .build();
    // 添加到configuration对象的ResultMap映射集合中
    configuration.addResultMap(resultMap);
    return resultMap;
}

<resultMap/>标签的解析到这里就完成了,下面是<sql/>标签的解析:
XMLMapperBuilder:

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

XMLMapperBuilder:

private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {
    for (XNode context : list) {
        // 提取databaseId配置
        String databaseId = context.getStringAttribute("databaseId");
        // 提取id配置
        String id = context.getStringAttribute("id");
        // 应用当前命名空间,命名空间+配置的id
        id = builderAssistant.applyCurrentNamespace(id, false);
        /* 判断databaseId配置是否匹配 */
        if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
            // 添加映射关系
            sqlFragments.put(id, context);
        }
    }
}

XMLMapperBuilder:

private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {
    // 如果配置了全局的databaseId,当判断当前<sql/>标签配置的databaseId与全局的databaseId是否相同
    if (requiredDatabaseId != null) {
        if (!requiredDatabaseId.equals(databaseId)) {
            return false;
        }
    } else {
        // 如果没有配置全局的databaseId,则当前<sql/>标签也不能配置databaseId
        if (databaseId != null) {
            return false;
        }
        // 如果id已经在映射关系中存在,则判断是否配置了databaseId
        if (this.sqlFragments.containsKey(id)) {
            XNode context = this.sqlFragments.get(id);
            if (context.getStringAttribute("databaseId") != null) {
                return false;
            }
        }
    }
    return true;
}

这里的<sql/>标签解析只是添加了映射,真正的应用才后面。下面是<select/><insert/><update/><delete/>四个标签的解析:
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枚举中找到对应的枚举值,如<select/>对应SELECT枚举值
    SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    // 提取flushCache配置,<select/>标签默认为false,其他为true
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    // 提取useCache配置,<select/>标签默认为true,其他为false
    boolean useCache = context.getBooleanAttribute("useCache", isSelect);
    boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);
    XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
    /* 应用<include/>包含的<sql/>片段 */
    includeParser.applyIncludes(context.getNode());
    /* 解析<selectkey/>标签 */
    processSelectKeyNodes(id, parameterTypeClass, langDriver);
    /* 创建SqlSource */
    SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
    String resultSets = context.getStringAttribute("resultSets");
    String keyProperty = context.getStringAttribute("keyProperty");
    String keyColumn = context.getStringAttribute("keyColumn");
    KeyGenerator keyGenerator;
    String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
    // 应用当前命名空间,命名空间+keyStatementId 
    keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
    // 不同情况的KeyGenerator选择
    if (configuration.hasKeyGenerator(keyStatementId)) {
        keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
        keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
            configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
        ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
    }
    /* 构建MappedStatement并添加到configuration对象中 */
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered, 
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}

XMLIncludeTransformer:

public void applyIncludes(Node source) {
    Properties variablesContext = new Properties();
    Properties configurationVariables = configuration.getVariables();
    if (configurationVariables != null) {
        // 复制一份configuration对象中的全局变量
        variablesContext.putAll(configurationVariables);
    }
    /* 应用包含的sql片段 */
    applyIncludes(source, variablesContext, false);
}

XMLIncludeTransformer:

private void applyIncludes(Node source, final Properties variablesContext, boolean included) {
    // 如果是<include/>标签
    if (source.getNodeName().equals("include")) {
        /* 提取refid对应的sql片段的Node */
        Node toInclude = findSqlFragment(getStringAttribute(source, "refid"), variablesContext);
        /* 从节点定义中读取占位符和它们的值 */
        Properties toIncludeContext = getVariablesContext(source, variablesContext);
        // 将包含的sql片段节点作为参数递归此方法
        applyIncludes(toInclude, toIncludeContext, true);
        if (toInclude.getOwnerDocument() != source.getOwnerDocument()) {
            // 如果当前节点和被包含节点不在同一个文档中,则将被包含节点导入当前节点所在的文档中
            toInclude = source.getOwnerDocument().importNode(toInclude, true);
        }
        // 将当前节点替换成被包含节点
        source.getParentNode().replaceChild(toInclude, source);
        while (toInclude.hasChildNodes()) {
            // 将子节点放在被包含节点的前面
            toInclude.getParentNode().insertBefore(toInclude.getFirstChild(), toInclude);
        }
        // 从父节点中移除被包含节点
        toInclude.getParentNode().removeChild(toInclude);
    } else if (source.getNodeType() == Node.ELEMENT_NODE) {
        NodeList children = source.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            // 如果是元素类型的Node如<select/>,就遍历子节点递归此方法
            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从之前解析<sql/>标签时添加的映射中获取对应的节点
        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); // 子节点也就是<property/>标签
        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;
    }
}

下面是<selectKey/>标签的解析
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提供的一些动态标签的处理器,如<where/><set/><foreach/>等,我们以<if/>标签为例来看它如何处理动态标签,而处理过后节点的应用则是在mapper方法执行的过程中,我们会在后续的文章中进行详细讲解,其他动态标签的处理也是类似的:
XMLScriptBuilder.IfHandler:

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

解析<selectKey/>标签最后是构建并添加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;
}

<selectKey/>标签解析完成了,下面会继续<select/><insert/><update/><delete/>四个标签的解析,后面的流程在解析<selectKey/>标签时已经分析过,同样都会创建SqlSource、解析动态标签、构建MappedStatement等,这里不再赘述。最后就是将解析好的Configuration对象封装到DefaultSqlSessionFactory中返回。
SqlSessionFactoryBuilder:

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

到这里,整个Mybatis标签解析的源码就分析完了。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一款开源的持久层框架,它支持自定义SQL、存储过程和高级映射。本文将深度解析MyBatis源码,包括其核心组件和实现原理。 1. MyBatis的核心组件 MyBatis的核心组件包括: - SqlSessionFactoryBuilder:用于创建SqlSessionFactory,它会读取配置文件并创建相应的对象。 - SqlSessionFactory:用于创建SqlSession,它是线程安全的,因此可以被共享。 - SqlSession:用于执行SQL语句,它是非线程安全的,因此每个线程都需要创建自己的SqlSession。 - Executor:用于执行SQL语句。 - StatementHandler:用于处理SQL语句的处理器。 - ParameterHandler:用于处理参数的处理器。 - ResultSetHandler:用于处理结果集的处理器。 - MappedStatement:映射配置信息,包括SQL语句、参数类型、返回值类型等。 - Configuration:MyBatis的配置信息,包括数据源、类型转换器、映射配置等。 2. MyBatis的实现原理 MyBatis的实现原理主要包括以下几个方面: 2.1 映射配置 MyBatis使用XML或注解的方式进行映射配置,其配置信息包括: - 映射文件的命名空间。 - 映射文件中定义的SQL语句,包括select、insert、update、delete等。 - SQL语句的参数类型和返回值类型。 - SQL语句的参数映射关系,包括#{paramName}形式的占位符和${paramName}形式的变量。 - SQL语句的结果映射关系,包括<resultMap>标签和<result>标签。 2.2 解析配置文件 MyBatis会通过SqlSessionFactoryBuilder读取配置文件,并将其解析成一个Configuration对象。解析过程中会进行数据源的配置、类型转换器的配置、映射配置的加载等。 2.3 创建SqlSessionFactory MyBatis解析配置文件之后,会根据配置信息创建SqlSessionFactory对象。SqlSessionFactory是线程安全的,因此可以被共享。它主要负责创建SqlSession对象。 2.4 创建SqlSession 每个SqlSession都会绑定一个Connection对象,因此它是非线程安全的。MyBatis会为每个线程创建自己的SqlSession对象。SqlSession主要负责执行SQL语句。 2.5 执行SQL语句 MyBatis执行SQL语句时,会先根据SQL语句的ID从MappedStatement中获取相应的映射信息,然后使用Executor执行SQL语句。在执行SQL语句时,会使用StatementHandler处理SQL语句,ParameterHandler处理参数,ResultSetHandler处理结果集。 3. 总结 本文深度解析MyBatis源码,包括其核心组件和实现原理。MyBatis是一个功能强大的持久层框架,可以帮助我们简化数据库操作。同时,MyBatis源码也值得我们深入学习和研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值