当前位置: 首页 > article >正文

从MyBatis-Plus看Spring Boot自动配置原理

一、问题引入:神秘的配置生效之谜

当我们使用MyBatis-Plus时,只需在pom.xml中添加依赖:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

然后在application.properties中配置:

mybatis-plus.mapper-locations=classpath*:mapper/*.xml

问题来了:我们既没有在代码中显式读取这个配置,也没有手动创建相关Bean,这些参数究竟是如何生效的?这就是Spring Boot自动配置的魔法所在!

二、Spring Boot自动配置机制揭秘

2.1 核心注解剖析

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

这个注解等价于:

@SpringBootConfiguration
@EnableAutoConfiguration  // 开启自动配置的核心注解
@ComponentScan

2.2 自动配置流程

  1. 触发机制:通过@EnableAutoConfiguration激活自动配置

  2. 配置收集:扫描所有META-INF/spring.factories文件

  3. 条件过滤:通过条件注解筛选有效配置类

  4. 执行顺序:通过@AutoConfigureOrder@AutoConfigureAfter控制加载顺序

  5. 配置生效:创建符合条件的Bean并加入IOC容器

2.3 条件注解全家福

注解名称生效条件
@ConditionalOnClass类路径存在指定类时生效
@ConditionalOnMissingBean容器中不存在指定Bean时生效
@ConditionalOnProperty配置文件中存在指定属性时生效
@ConditionalOnWebApplicationWeb应用环境下生效

三、MyBatis-Plus自动配置深度解析

3.1 自动配置入口

mybatis-plus-boot-starterMETA-INF/spring.factories中:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration

3.2 核心配置类分析

@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@EnableConfigurationProperties(MybatisPlusProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisPlusAutoConfiguration {
    // 核心配置逻辑
}

注解解析

  • @ConditionalOnClass:确保MyBatis核心类存在

  • @EnableConfigurationProperties:绑定配置属性

  • @AutoConfigureAfter:确保数据源先配置完成

3.3 配置属性绑定

@ConfigurationProperties(prefix = "mybatis-plus")
public class MybatisPlusProperties {
    private String[] mapperLocations;
    private String typeAliasesPackage;
    private Class<?> typeEnumsPackage;
    // 其他配置项及getter/setter
}

属性映射过程

  1. Spring Boot启动时扫描@ConfigurationProperties

  2. application.propertiesmybatis-plus前缀的配置

  3. 通过Setter方法注入到MybatisPlusProperties实例

3.4 SqlSessionFactory自动配置

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    factory.setMapperLocations(
        Stream.of(properties.getMapperLocations())
              .flatMap(loc -> Arrays.stream(resources.getResources(loc)))
              .toArray(Resource[]::new)
    );
    // 其他配置项处理...
    return factory.getObject();
}

关键逻辑

  • 自动注入DataSource(来自数据源自动配置)

  • 解析mapper.xml路径(支持Ant风格路径)

  • 处理类型别名、插件等扩展配置

3.5 Mapper接口注册机制

@Bean
@ConditionalOnMissingBean
public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurer configurer = new MapperScannerConfigurer();
    configurer.setBasePackage("${mybatis-plus.mapper-package}");
    return configurer;
}

扫描规则

  1. 默认扫描@Mapper注解的接口

  2. 支持通过配置mybatis-plus.mapper-package指定扫描路径

  3. 自动将接口代理实现类注册为Spring Bean

3.6 条件配置的精妙之处

@ConditionalOnMissingBean(SqlSessionFactory.class)
public class MybatisPlusAutoConfiguration {
    // 当用户没有自定义SqlSessionFactory时生效
}

这种设计实现了:

  1. 开箱即用:默认配置满足大部分场景

  2. 灵活覆盖:允许用户自定义Bean来替代自动配置

  3. 按需加载:只有相关依赖存在时才生效

四、自动配置的调试技巧

4.1 查看生效的自动配置类

启动时添加VM参数:

-Ddebug=true

输出示例:

MybatisPlusAutoConfiguration matched:
   - @ConditionalOnClass found required classes [...]
   - @ConditionalOnMissingBean [...] none found

4.2 排除指定自动配置类

@SpringBootApplication(exclude = {MybatisPlusAutoConfiguration.class})

五、最佳实践建议

  1. 谨慎覆盖:尽量通过配置参数调整,而非直接覆盖自动配置Bean

  2. 明确扫描路径:明确指定@MapperScan("com.xxx.mapper")

  3. 版本对齐:保持starter父工程与MyBatis-Plus版本一致

  4. 配置检查:善用spring.config.activate.on-profile进行环境隔离

六、总结

通过分析MyBatis-Plus的自动配置实现,我们可以深入理解Spring Boot自动配置的三大核心:

  1. 约定优于配置:通过标准化配置路径和命名减少样板代码

  2. 条件化装配:智能判断运行环境,按需加载组件

  3. 扩展机制:通过starter和spring.factories实现模块化装配

这种设计使得Spring Boot应用既能快速启动,又保持了高度的灵活性,堪称框架设计的典范。掌握自动配置原理,就能在遇到配置问题时快速定位,在需要扩展时游刃有余。


http://www.kler.cn/a/540765.html

相关文章:

  • 采用分步式无线控制架构实现水池液位自动化管理
  • Day82:创建图形界面(GUI)
  • Qt通过FFmpeg打开RTSP并截图一帧作为背景
  • SpringBoot速成(八)登录实战:未登录不能访问 P5-P8
  • 【DeepSeek】DeepSeek概述 | 本地部署deepseek
  • 利用 Python 爬虫获取按关键字搜索淘宝商品的完整指南
  • 继承(python)
  • 2/10QT
  • centos系统清理docker日志文件
  • 【PG】DROP TABLE ... CASCADE
  • 《qt easy3d中添加孔洞填充》
  • 持续集成CI(Continuous Integration)
  • Unity笔试常考
  • 没用的文章又➕1
  • 如何使用Xcode进行iOS应用开发?
  • 如何定义“破坏环境”
  • pnpm的指令和优点
  • 阿里AI通义千问官网入口、APP下载,使用教程
  • 本地部署deepseek-r1:7b模型
  • 8、Python 面试题解析:实例方法、静态方法和类方法的区别
  • w~自动驾驶~合集17
  • C#程式状态机及其Godot实践
  • Docker的深入浅出
  • 如何利用DeepSeek结合深度学习与NLP技术,实现跨模态搜索的语义理解与个性化推荐
  • Firefox无法隐藏标题栏
  • 单片机成长之路(51基础篇) - 008 C51 的标示符和关键字