在使用 Spring Boot 构建多模块项目,集成 MyBatis-Plus 时,很多开发者会遇到类似如下启动报错:
Error creating bean with name 'mapperScannerConfigurer' ...
Caused by: java.lang.IllegalArgumentException: Property 'basePackage' is required
即使在启动类上正确添加了 @MapperScan("com.xxx.mapper")
,项目依然报错无法启动。这到底是怎么回事?我们该如何优雅地配置 Mapper
扫描?本文将逐步分析问题成因,最后给出推荐方案。
一、问题背景
项目结构如下(典型的多模块结构):
parent
├── common # 公共模块,封装配置类等
├── user # 业务模块,包含启动类、Mapper 接口
└── pom.xml
在 user
模块中有如下启动类:
@SpringBootApplication
@MapperScan("com.partner.user.mapper")
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}
在 common
模块中配置了如下 MybatisPlusConfig
:
@Configuration
@EnableConfigurationProperties(MyBatisPlusProperties.class)
public class MybatisPlusConfig {@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(MyBatisPlusProperties myBatisPlusProperties) {System.out.println("Mapper scan package: " + myBatisPlusProperties.getMapperScan());MapperScannerConfigurer configurer = new MapperScannerConfigurer();configurer.setBasePackage(myBatisPlusProperties.getMapperScan());return configurer;}
}
配置类依赖的配置文件如下(写在 user
模块的 bootstrap.yml
):
mybatis:mapperScan: com.partner.user.mapper
二、项目启动失败的根本原因
启动失败栈信息:
Caused by: java.lang.IllegalArgumentException: Property 'basePackage' is required
也就是说:MapperScannerConfigurer
没有成功读取到 basePackage
,传入的是 null。从而导致 afterPropertiesSet()
抛出异常。
根本原因是:
MapperScannerConfigurer
是一个 Spring Bean,提前初始化,但它依赖的mybatis.mapperScan
配置却定义在bootstrap.yml
中,属于 Spring Cloud 的配置生命周期,尚未加载完成,导致值为null
。
三、常见误区总结
错误实践 | 原因 |
---|---|
配置 MapperScannerConfigurer 并从 bootstrap.yml 读取 mapperScan | 配置未加载时就被调用,null 值引发异常 |
在多个模块分别配置 mapper 扫描路径 | 不同模块配置加载顺序不确定,容易互相覆盖或无效 |
同时使用 @MapperScan 和 MapperScannerConfigurer | 存在重复扫描、不一致行为风险 |
四、推荐解决方案
✅ 推荐做法:只使用 @MapperScan
注解,彻底抛弃 MapperScannerConfigurer
这是最简洁、最稳定的做法,推荐如下方式:
1. 在启动类中添加注解:
@SpringBootApplication
@MapperScan("com.partner.user.mapper") // 替换为你自己的 mapper 包路径
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}
2. 删除 MapperScannerConfigurer
相关 Bean:
// ❌ 删除该 Bean,否则仍然会因配置未加载而报错
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(...) {...
}
这样一来,MyBatis-Plus 会根据注解自动扫描 Mapper 接口,避免复杂配置和潜在异常。
五、其他可选做法(不推荐)
如果你确实有特殊需求,想动态配置扫描路径,也应注意以下几点:
-
配置写在
application.yml
而非bootstrap.yml
,确保其生命周期早于 Bean 初始化; -
或使用 Spring Boot 2.2+ 的
@ConfigurationPropertiesScan
自动扫描配置类。
示例:
@ConfigurationProperties(prefix = "mybatis")
public class MyBatisPlusProperties {private String mapperScan;
}@Configuration
@ConfigurationPropertiesScan("com.partner.common.config")
public class MybatisPlusConfig {...
}
六、总结建议
方案 | 是否推荐 | 说明 |
---|---|---|
@MapperScan("xxx") 注解 | ✅ 推荐 | 简单高效,避免生命周期问题 |
自定义配置类读取扫描包路径 | ❌ 不推荐 | 配置不易统一,生命周期难控制 |
多模块共用一个配置类 + 注解扫描 | ✅ 推荐 | 公共模块做分页拦截器等配置,Mapper 扫描交给启动类注解 |
七、写在最后
在实际开发中,越是多模块复杂项目,越应该避免不必要的配置项和手动扫描逻辑。优雅使用 @MapperScan
是最稳定的 MyBatis 配置方案。
如果你也遇到了类似的问题,希望这篇文章能帮你少走弯路!
📌如果本文对你有帮助,欢迎点赞、收藏、评论支持一下!
📮如有更多 Spring Boot 多模块踩坑问题,欢迎留言交流~