Spring Boot中MyBatis Plus多数据源Mapper注入冲突问题排查实录

张开发
2026/4/16 20:35:55 15 分钟阅读

分享文章

Spring Boot中MyBatis Plus多数据源Mapper注入冲突问题排查实录
作者azzlle时间2026年4月15日关键词Spring Boot, MyBatis Plus, 多数据源, Resource注入, Bean冲突一、问题背景在采用多数据源架构传统MySQL数据库用于业务数据MGR数据源Doris数据库用于大数据分析MPP数据源。项目使用Spring Boot MyBatis Plus框架。最近在重构过程中新增了Doris数据源的Mapper接口DorisBaseMapper但应用启动时频繁报错无法注入正确的Bean。二、错误现象应用启动时抛出以下异常Description: The bean bankCustMapper could not be injected because it is a JDK dynamic proxy The bean is of type jdk.proxy2.$Proxy254 and implements: com.example.project.service.mapper.mgr.CustomMapper Expected a bean of type com.example.project.service.mapper.mpp.DorisBaseMapper which implements: com.baomidou.mybatisplus.core.mapper.BaseMapper Action: Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClasstrue on EnableAsync and/or EnableCaching.关键信息提取期望类型DorisBaseMapper继承BaseMapper实际类型CustomMapper的JDK动态代理$Proxy254Bean名称bankCustMapper三、深层分析Resource按名称注入的陷阱经过初步排查确认问题并非简单的XML配置错误或MyBatis映射问题。核心矛盾点在于Spring Bean注入机制中的名称匹配规则。3.1 检查Service实现类Service RequiredArgsConstructor ConditionalOnExpression(${ DorisDataSourceProp.DORIS_ENABLE_PROPERTIES_KEY }.equals(true)) public class DorisBaseServiceImpl implements DorisBaseService { Resource // 关键点使用Resource按名称注入 private final DorisBaseMapper bankCustMapper; // ... }3.2 Spring Bean注册情况Bean类型默认Bean名称实现接口数据源CustomMapperbankCustMapper自定义接口MGR数据源DorisBaseMapperdorisBaseMapper继承BaseMapperDoris数据源3.3 Resource注解的行为分析Resource注解的注入规则默认按名称匹配先按字段名bankCustMapper查找对应Bean名称匹配失败时再按类型匹配名称匹配成功即使类型不兼容也会注入导致类型转换异常关键发现字段名bankCustMapper正好匹配到了CustomMapper接口的Bean而不是期望的DorisBaseMapper。3.4 方法签名重叠加剧问题// CustomMapper.javaMGR数据源 ListPersonalCustomerVO listPrivateCustomers(PersonalCustParam customerQueryParam); // DorisBaseMapper.javaDoris数据源 ListPersonalCustomerVO listPrivateCustomers(PersonalCustParam customerQueryParam); // 同名方法同名方法的存在使得两个Mapper接口在某种程度上相似但它们的继承关系不同CustomMapper自定义接口无基类DorisBaseMapper继承BaseMapperBaseEntity四、根本原因Resource按名称注入的陷阱4.1 注入流程分析Resource private final DorisBaseMapper bankCustMapper;Spring容器的Bean查找过程查找名称为bankCustMapper的Bean → 找到CustomMapper的实例尝试将CustomMapper实例赋值给DorisBaseMapper类型的字段类型不兼容CustomMapper没有实现BaseMapper接口抛出异常Expected a bean of type DorisBaseMapper which implements BaseMapper4.2 多数据源配置的复杂性项目中有两套数据源配置// MGR数据源配置 Configuration MapperScan(basePackages com.example.project.service.mapper.mgr) public class DataSourceConfig { /* ... */ } // Doris数据源配置 Configuration ConditionalOnExpression(${project.mpp.jdbc.enable}.equals(true)) MapperScan(basePackages com.example.project.service.mapper.mpp) public class MppDataSourceConfig { /* ... */ }当Doris数据源启用时project.mpp.jdbc.enabletrue两个数据源配置同时生效导致两个同名的Bean同时存在。五、解决方案方案一使用Qualifier明确指定Bean推荐Service RequiredArgsConstructor ConditionalOnExpression(${ DorisDataSourceProp.DORIS_ENABLE_PROPERTIES_KEY }.equals(true)) public class DorisBaseServiceImpl implements DorisBaseService { Resource Qualifier(dorisBaseMapper) // 明确指定Bean名称 private final DorisBaseMapper bankCustMapper; // ... }方案二使用Autowired按类型注入Autowired // 改为按类型注入 private final DorisBaseMapper bankCustMapper;方案三统一字段命名规范// 将字段名改为与Bean名称一致 Resource private final DorisBaseMapper dorisBaseMapper; // 字段名与Bean名称一致

更多文章