MyBatis 核心架构与启动流程剖析:从配置到初始化的深度解析

MyBatis 核心架构与启动流程剖析:从配置到初始化

  • [一、MyBatis 核心架构设计](#一、MyBatis 核心架构设计)
  • [二、MyBatis 启动流程全解析](#二、MyBatis 启动流程全解析)
    • [2.1 配置加载阶段:从 XML 到 Configuration 对象](#2.1 配置加载阶段:从 XML 到 Configuration 对象)
    • [2.2 核心类初始化:Configuration 的构建](#2.2 核心类初始化:Configuration 的构建)
    • [2.3 会话工厂构建:SqlSessionFactory 的创建](#2.3 会话工厂构建:SqlSessionFactory 的创建)
  • 三、关键流程图
    • [3.1 MyBatis 启动核心流程](#3.1 MyBatis 启动核心流程)
    • [3.2 MyBatis 映射器解析流程](#3.2 MyBatis 映射器解析流程)
    • [3.3 MyBatis 执行器初始化流程](#3.3 MyBatis 执行器初始化流程)
  • 四、核心类介绍
  • 五、总结

Mybatis的demo项目

user表的DDL 语句:

sql 复制代码
CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `name` varchar(50) DEFAULT NULL COMMENT '用户姓名',
  `age` int DEFAULT NULL COMMENT '用户年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';

User类:

java 复制代码
@Data
public class User {
    private int id;
    private String name;
    private int age;
}

UserMapper类:

java 复制代码
public interface UserMapper {
    User getUserById(int id);
}

UserMapper.xml:

xml 复制代码
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.coderzpw.dao.UserMapper">
    <select id="getUserById" resultType="com.coderzpw.domain.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

Mybatis主配置:

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!-- 环境配置 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--  配置连接数据库的四个参数 注意数据库版本  -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_study" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <!-- 设置mapping文件路径配置 -->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

测试类:

java 复制代码
public class MybatisTest {

    private SqlSessionFactory sessionFactory;

    /**
     * 加载配置文件。并且初始化SqlSessionFactory
     */
    @Before
    public void before() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    }
    
    @Test
    public void testGetById() {
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(1);
        System.out.println(user);
    }
}

一、MyBatis 核心架构设计

MyBatis 作为一款优秀的持久层框架,其架构设计遵循 "约定优于配置" 的原则,通过分层设计实现了数据库操作的解耦。核心架构主要分为以下几层:

1. 配置层(Configuration Layer)

  • 作用 :负责加载 MyBatis 配置文件(mybatis-config.xml)及映射文件(.xml
    或注解),构建框架运行时所需的元数据
  • 核心类Configuration(存储全局配置信息,如数据源、插件、映射器等)

2. 会话层(Session Layer)

  • 作用:提供数据库操作的会话接口,封装 SQL 的执行逻辑
  • 核心类
    • SqlSessionFactory(会话工厂,用于创建 SqlSession
    • SqlSession(会话接口,包含增删改查等方法)

3. 执行层(Executor Layer)

  • 作用:负责 SQL 的解析、参数映射、结果集转换等具体执行逻辑。
  • 核心类
    • Executor(执行器,处理 SQL 执行流程,支持简单、复用、批量执行模式)
    • StatementHandler(语句处理器,封装 PreparedStatement 的操作)

4. 数据层(Data Layer)

  • 作用:与数据库建立连接,执行物理 IO 操作。
  • 核心类DataSource(数据源,管理数据库连接)、Transaction(事务管理)。

二、MyBatis 启动流程全解析

MyBatis 的启动流程可分为 配置加载核心类初始化会话工厂构建 三个阶段,下面结合源码详细分析

java 复制代码
public SqlSessionFactory build(InputStream inputStream) {
  return build(inputStream, null, null);
}
java 复制代码
// 核心方法:通过 XML 构建 SqlSessionFactory
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
        // 解析 XML 配置文件,生成 Configuration 对象
        final XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
        final Configuration config = parser.parse(); // 关键方法
        // 构建 SqlSessionFactory(默认使用 DefaultSqlSessionFactory)
        return new DefaultSqlSessionFactory(config);
    } finally {
        ErrorContext.instance().reset();
        try {
            reader.close();
        } catch (IOException e) {
            // 异常处理
        }
    }
}

2.1 配置加载阶段:从 XML 到 Configuration 对象

XMLConfigBuilder.parse () 解析逻辑

java 复制代码
public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}
java 复制代码
  private void parseConfiguration(XNode root) {
    try {
      // 解析 properties 节点(外部属性)
      propertiesElement(root.evalNode("properties"));
      // 解析 settings 节点(全局配置项,如延迟加载、缓存等
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      // 解析 typeAliases 类型别名
      typeAliasesElement(root.evalNode("typeAliases"));
      // 解析 plugins 插件
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // 解析 environments 节点(包含数据源配置)
      environmentsElement(root.evalNode("environments"));
      // 解析 databaseIdProvider 数据库厂商识别
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      // 【重点】:解析 mappers 节点(SQL 映射文件)
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

关键步骤:加载映射器(mappersElement)

java 复制代码
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) {
          // 从类路径加载 XML 映射文件
          ErrorContext.instance().resource(resource);
          InputStream inputStream = Resources.getResourceAsStream(resource);
          XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
          mapperParser.parse();	// 解析 XML 中的 SQL 语句
        } else if (resource == null && url != null && mapperClass == null) {	
          // 从 URL 加载映射文件
          ErrorContext.instance().resource(url);
          InputStream inputStream = Resources.getUrlAsStream(url);
          XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
          mapperParser.parse();
        } else if (resource == null && url == null && mapperClass != null) {
          // 注册接口(通过注解配置 SQL)
          Class<?> mapperInterface = Resources.classForName(mapperClass);
          configuration.addMapper(mapperInterface);
        } else {
          throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
        }
      }
    }
  }
}

2.2 核心类初始化:Configuration 的构建

其实代码走完parseConfiguration()configuration对象就已经初始化完成了

Configuration 是 MyBatis 的 "大脑",存储了框架运行所需的所有元数据,其关键属性包括:

java 复制代码
public class Configuration {
    // 数据源与事务
    protected Environment environment; // 环境配置(数据源、事务工厂)
    
    // 映射器与 SQL 缓存
    protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection"); // 存储解析后的 SQL 语句
    protected final Map<String, SqlSource> sqlFragments = new StrictMap<SqlSource>("XML fragments"); // 存储 <sql> 片段
    
    // 类型处理器与对象工厂
    protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(this); // 类型转换注册器
    protected final ObjectFactory objectFactory = new DefaultObjectFactory(); // 对象工厂
    protected final ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory(); // 对象包装工厂
    
    // 插件链
    protected final InterceptorChain interceptorChain = new InterceptorChain(); // 插件链
    // ...
}

初始化流程关键点:

  1. 类型别名注册 :将 java.lang.Integer 等类型映射为 int 等简称,简化配置
  2. 插件注册 :通过 interceptorChain.addInterceptor(plugin) 将插件织入目标对象(如 ExecutorStatementHandler 等)
  3. 映射器注册 :将接口和 XML 中的 SQL 语句关联,生成 MappedStatement 对象(包含 SQL 语句、参数类型、结果集映射等信息)

2.3 会话工厂构建:SqlSessionFactory 的创建

核心类:DefaultSqlSessionFactory

java 复制代码
public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration; // 持有 Configuration 对象
	
	// 构造函数
    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public SqlSession openSession() {
        // 创建会话时指定执行器类型(默认 SIMPLE)
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
    }

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction transaction = null;
        try {
            // 1. 获取环境配置中的事务工厂
            final Environment environment = configuration.getEnvironment();
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            // 2. 创建事务对象(连接管理)
            transaction = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            // 3. 创建执行器(Executor)
            final Executor executor = configuration.newExecutor(transaction, execType);
            // 4. 创建 SqlSession(默认使用 DefaultSqlSession)
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(transaction); // 异常时关闭事务
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }
}

执行器(Executor)初始化逻辑

java 复制代码
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
        executor = new BatchExecutor(this, transaction); // 批量执行器
    } else if (ExecutorType.REUSE == executorType) {
        executor = new ReuseExecutor(this, transaction); // 可重用执行器(缓存 Statement)
    } else {
        executor = new SimpleExecutor(this, transaction); // 简单执行器(每次创建新 Statement)
    }
    // 插件拦截器链:为执行器添加插件功能
    if (cacheEnabled) {
        executor = new CachingExecutor(executor); // 装饰器模式,添加缓存功能
    }
    // 应用插件(重点!通过 InterceptorChain 对目标对象进行包装)
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
}

三、关键流程图

3.1 MyBatis 启动核心流程

java 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                          配置加载阶段                                │
│                                                                     │
│  SqlSessionFactoryBuilder.build()                                    │
│      └── XMLConfigBuilder.parse()                                    │
│          ├── propertiesElement()   解析外部属性                      │
│          ├── settingsElement()     解析全局配置                      │
│          ├── typeAliasesElement()  解析类型别名                      │
│          ├── pluginElement()       解析插件配置                      │
│          ├── environmentsElement() 解析数据源与事务配置              │
│          ├── databaseIdProviderElement() 解析数据库厂商识别           │
│          └── mappersElement()      解析映射器文件                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────────────┐
│                          核心类初始化阶段                            │
│                                                                     │
│  Configuration 对象构建                                             │
│      ├── 注册类型别名(简化配置书写)                               │
│      ├── 注册插件(InterceptorChain 管理)                          │
│      ├── 注册映射器(生成 MappedStatement 集合)                    │
│      ├── 管理数据源与事务配置(Environment、DataSource)             │
│      └── 维护类型处理器与对象工厂(TypeHandlerRegistry、ObjectFactory)│
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────────────┐
│                          会话工厂构建阶段                            │
│                                                                     │
│  DefaultSqlSessionFactory 创建                                      │
│      ├── 持有 Configuration 对象                                   │
│      ├── openSession() 方法创建 SqlSession                          │
│      │   ├── 获取 Environment 配置                                 │
│      │   ├── 创建事务对象(TransactionFactory.newTransaction())     │
│      │   ├── 创建执行器(Configuration.newExecutor())              │
│      │   │   ├── 根据类型创建 Simple/Reuse/Batch Executor           │
│      │   │   ├── 启用缓存时包裹 CachingExecutor                     │
│      │   │   └── 应用插件链(InterceptorChain.pluginAll())          │
│      │   └── 创建 DefaultSqlSession(持有 config 和 executor)        │
│      └── 提供会话创建入口,是应用与 MyBatis 交互起点                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3.2 MyBatis 映射器解析流程

java 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                          映射器解析阶段                              │
│                                                                     │
│  mappersElement 方法解析                                             │
│      ├── 按包扫描(<package> 标签)                                  │
│      │   └── 注册包下所有接口(Configuration.addMappers())           │
│      ├── 加载单个映射文件(<resource>/<url>/<class> 标签)            │
│      │   ├── <resource> 从类路径加载 XML 映射文件                    │
│      │   │   ├── 创建 XMLMapperBuilder 解析器                        │
│      │   │   ├── 解析 XML 中的 SQL 语句(生成 MappedStatement)       │
│      │   │   └── 注册到 Configuration 的 mappedStatements 集合        │
│      │   ├── <url> 从 URL 加载映射文件                              │
│      │   └── <class> 注册接口(通过注解配置 SQL)                     │
│      └── 建立接口与 XML 中 SQL 语句的关联关系                        │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

3.3 MyBatis 执行器初始化流程

java 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                          执行器初始化阶段                            │
│                                                                     │
│  Configuration.newExecutor() 方法                                    │
│      ├── 根据 ExecutorType 创建基础执行器                            │
│      │   ├── ExecutorType.BATCH -> BatchExecutor                      │
│      │   ├── ExecutorType.REUSE -> ReuseExecutor                      │
│      │   └── 默认 ExecutorType.SIMPLE -> SimpleExecutor                │
│      ├── 检查是否启用缓存(cacheEnabled)                            │
│      │   └── 是则使用 CachingExecutor 装饰器包装                      │
│      ├── 应用插件链(InterceptorChain.pluginAll())                   │
│      │   ├── 遍历插件集合(interceptors)                            │
│      │   ├── 对每个插件调用 plugin(target) 方法进行包装              │
│      │   └── 返回增强后的执行器对象                                  │
│      └── 生成具备 SQL 执行、缓存处理、插件增强能力的执行器           │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

四、核心类介绍

核心类 作用描述
Configuration 存储全局配置信息,是 MyBatis 的 "配置中心",贯穿整个启动流程
SqlSessionFactory 工厂类,负责创建 SqlSession,是应用与 MyBatis 交互的入口
Executor 执行 SQL 的核心组件,处理参数映射、结果集转换,支持不同执行策略(简单 / 批量 / 复用)
MappedStatement 单条 SQL 的封装对象,包含 SQL 语句、参数类型、结果映射等元数据

五、总结

MyBatis 的启动流程是一个典型的 "配置驱动 " 过程,通过解析 XML 配置文件构建运行时所需的元数据,然后基于这些元数据创建核心组件。整个过程可以概括为:

  1. 配置解析阶段 :从 XML 配置文件中读取配置信息,构建 Configuration 对象
  2. 核心类初始化阶段 :初始化 Configuration 中的各种组件,如数据源、映射器、插件等
  3. 会话工厂构建阶段 :创建 SqlSessionFactory,用于后续创建 SqlSession
  4. 执行器初始化阶段 :创建不同类型的执行器,处理 SQL 执行逻辑

理解 MyBatis 的启动流程有助于我们更好地使用和优化 MyBatis,例如通过自定义插件扩展功能,通过合理配置提高性能,以及在遇到问题时能够快速定位和解决

相关推荐
hstar95275 分钟前
三十一、面向对象底层逻辑-SpringMVC九大组件之RequestToViewNameTranslator接口设计哲学
java·spring·设计模式·架构
米粉030510 分钟前
Spring Boot 接口开发实战指南
java·spring boot·后端
chian-ocean21 分钟前
深入解析Linux死锁:原理、原因及解决方案
java·linux·redis
oioihoii22 分钟前
C++23:std::print和std::println格式化输出新体验
java·开发语言·c++23
Sherlock Ma30 分钟前
MySQL:零基础入门(狂神版)
java·数据库·程序人生·mysql·职场和发展·学习方法·改行学it
知月玄33 分钟前
网页前端开发(基础进阶1)
java·前端·javascript·css
啥都想学的又啥都不会的研究生33 分钟前
常规算法学习
java·数据结构·b树·学习·算法·排序算法
凌佚1 小时前
在飞牛nas系统上部署gitlab
java·开发语言·gitlab
残*影1 小时前
深入解析 BlockingQueue:并发编程面试中的高频考点!
java·面试
sunny052962 小时前
sl4j+log4j日志框架
java·log4j