MyBatis与MyBatis-Plus共存时,如何优雅解决Mapper扫描冲突?
在构建现代Java企业级应用时,很多团队会面临一个看似微小却令人头疼的问题:项目初期可能基于经典的MyBatis框架构建,随着业务复杂度的提升,为了提升开发效率,又引入了功能更强大的MyBatis-Plus。当这两个框架在同一个Spring Boot项目中并存时,一个典型的“警告”便会悄然出现在启动日志中——Bean already defined with the same name!。这不仅仅是控制台里几行碍眼的黄色文字,它背后反映的是Spring容器中Bean定义的潜在冲突。对于追求代码整洁和架构清晰的开发者而言,这种警告如同鞋里的一粒沙子,虽不致命,却总让人无法忽视。今天,我们就来深入探讨这个问题的根源,并提供一套清晰、可落地的解决方案,让你在5分钟内彻底搞定配置冲突,让项目启动日志恢复清爽。
1. 冲突的根源:当两个扫描器相遇
要解决问题,首先要理解问题是如何产生的。MyBatis和MyBatis-Plus虽然同源,但在Spring Boot的自动配置和Bean注册机制上,它们各自为政,都试图将自己管理的Mapper接口注册为Spring容器中的Bean。
核心冲突点在于 @MapperScan 注解。这个注解是MyBatis-Spring整合包提供的,它的作用是告诉Spring,在哪些包路径下寻找Mapper接口,并为它们创建代理对象(MapperFactoryBean)注册到容器中。MyBatis-Plus为了保持兼容性,也完全支持并使用这个注解。
想象一下这个场景:你的项目结构如下:
com.example.demo
├── mapper
│ ├── UserMapper.java // 使用原生MyBatis注解或XML
│ └── OrderMapper.java
└── plusmapper
├── ProductMapper.java // 继承自MyBatis-Plus的BaseMapper
└── CategoryMapper.java
然后,你在配置类中可能这样写:
// MyBatis 配置类
@Configuration
@MapperScan("com.example.demo.**.mapper")
public class MyBatisConfig {
// 配置数据源、事务管理器等
}
// MyBatis-Plus 配置类
@Configuration
@MapperScan("com.example.demo.**.mapper")
public class MyBatisPlusConfig {
// 配置分页插件、性能分析插件等
}
或者更常见的是,你只在其中一个配置类上使用了 @MapperScan,但扫描路径使用了过于宽泛的通配符,如 com.example.demo.**.mapper,这个路径可能意外地覆盖了另一个框架本该管理的Mapper。
当Spring启动时,它会处理这些配置类。如果两个 @MapperScan 注解指定的扫描路径存在重叠(无论是完全一样,还是因为通配符导致包含关系),Spring就会尝试为同一个Mapper接口(例如 com.example.demo.mapper.UserMapper)创建两个 MapperFactoryBean 实例。Spring容器不允许存在两个同名的Bean(默认以类名首字母小写作为Bean名称),因此后一个扫描器在尝试注册时,会发现该Bean已存在,于是抛出我们看到的警告:
WARN org.mybatis.spring.mapper.ClassPathMapperScanner - Skipping MapperFactoryBe



被折叠的 条评论
为什么被折叠?



