MyBatis-Plus 源码阅读(二):只引入一个 Starter,启动时发生了什么

MyBatis-Plus 源码阅读(二):只引入一个 Starter,启动时发生了什么

平时接入 MyBatis-Plus,大多只加一个 Starter,再写个 @MapperScan。

业务代码里没有手动创建 SqlSessionFactory,也没有注册 BaseMapper。这些东西从哪里来的?

答案在 MybatisPlusAutoConfiguration。

自动配置什么时候生效

先看类上的几个条件:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisPlusProperties.class)
public class MybatisPlusAutoConfiguration {
}

翻成人话就是:

  • classpath 里得有 MyBatis 和 MyBatis-Spring;
  • Spring 容器里得有一个明确的数据源;
  • mybatis-plus.* 配置会绑定到 MybatisPlusProperties;
  • 条件满足后,这个自动配置类才开始干活。

如果项目里有多个 DataSource,又没有标明哪个是主要候选者,这段自动配置可能根本不会生效。这类问题只看 Mapper 报错,往往找不到原因。

最重要的 Bean:SqlSessionFactory

sqlSessionFactory(DataSource) 是这篇的主入口。

它没有使用 MyBatis-Spring 原生的 SqlSessionFactoryBean,而是创建:

MybatisSqlSessionFactoryBean factory =
    new MybatisSqlSessionFactoryBean();

接着往工厂里放入数据源、MybatisConfiguration、Mapper XML 地址、插件、TypeHandler、LanguageDriver 和 GlobalConfig。

我们自己声明的几个 Bean,也是在这里被接走的:

MetaObjectHandler
AnnotationHandler
PostInitTableInfoHandler
IKeyGenerator
ISqlInjector
IdentifierGenerator

例如项目中放一个 MetaObjectHandler Bean,不需要再手动塞进 MyBatis。自动配置会找到它,再放入 GlobalConfig。

MybatisConfiguration 从哪来

applyConfiguration() 会根据配置文件情况决定 Configuration 的来源。

没有指定原生 MyBatis 配置文件时,默认创建:

new MybatisConfiguration()

它继承 MyBatis 的 Configuration,但增强了几处关键行为:

  • 使用 MybatisMapperRegistry;
  • 默认开启下划线转驼峰;
  • 默认使用组合枚举 TypeHandler;
  • 默认使用 MybatisXMLLanguageDriver;
  • 调整同名 MappedStatement 的处理方式。

MyBatis-Plus 没有丢掉 MyBatis Configuration,只是在它上面换了几个自己需要的零件。

FactoryBean 真正构建了什么

MybatisSqlSessionFactoryBean.buildSqlSessionFactory() 的顺序可以缩成:

确定 Configuration
    -> 绑定 GlobalConfig
    -> 注册别名、插件、TypeHandler、LanguageDriver
    -> 创建 Environment
    -> 解析 Mapper XML
    -> MybatisSqlSessionFactoryBuilder.build()
    -> 得到 SqlSessionFactory

Environment 把数据源和事务工厂交给 MyBatis。在 Spring 环境里,默认使用 SpringManagedTransactionFactory,事务仍由 Spring 管。

Mapper 是怎么被扫进来的

这里有两种情况。

项目显式写了:

@MapperScan("com.example.mapper")

那么 MyBatis-Spring 的扫描器负责注册 Mapper。

如果没有 @MapperScan,也没有自己配置 MapperFactoryBean 或 MapperScannerConfigurer,自动配置中的 AutoConfiguredMapperScannerRegistrar 会兜底扫描。

但这个兜底扫描只找带 @Mapper 的接口:

// 有 @MapperScan 时,可以不写 @Mapper
public interface UserMapper extends BaseMapper<User> {
}
// 依赖自动配置兜底扫描时,需要 @Mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

SqlSessionTemplate 又是什么

自动配置还会创建 SqlSessionTemplate。

它是 MyBatis-Spring 提供的线程安全 SqlSession 门面。Mapper 最终通过它参与 Spring 事务,并获取、释放真正的会话。

到这里,Spring 和 MyBatis 的连接就搭好了:

DataSource
    -> MybatisSqlSessionFactoryBean
    -> SqlSessionFactory
    -> SqlSessionTemplate
    -> MapperFactoryBean
    -> Mapper 代理

怎么验证

在上一篇的 H2 项目里加一个测试:

@Autowired
private SqlSessionFactory sqlSessionFactory;

@Autowired
private SqlSessionTemplate sqlSessionTemplate;

@Test
void shouldUseMybatisPlusConfiguration() {
    Configuration configuration =
        sqlSessionFactory.getConfiguration();

    assertInstanceOf(
        MybatisConfiguration.class,
        configuration
    );
    assertSame(
        sqlSessionFactory,
        sqlSessionTemplate.getSqlSessionFactory()
    );
}
posted @ 2026-09-20 17:11  01o00o10  阅读(17)  评论(0)    收藏  举报