注意不要混用@MapperScan和@ComponentScan

本文讲述了在Spring框架中,@MapperScan和@ComponentScan注解的区别。@ComponentScan用于扫描@Controller、@Service、@Repository等组件,而@MapperScan专门用于扫描Mapper接口。当在main方法中误用@ComponentScan替代@MapperScan时,会导致Bean创建失败,报NoSuchBeanDefinitionException。解决方案是恢复使用@MapperScan注解。了解这两个注解的正确使用对于Spring应用的配置至关重要。

1、首先@MapperScan和@ComponentScan都是扫描包

2、@ComponentScan是组件扫描注解,用来扫描@Controller  @Service  @Repository这类,主要就是定义扫描的路径从中找出标志了需要装配的类到Spring容器中

3、@MapperScan 是扫描mapper类的注解,就不用在每个mapper类上加@MapperScan了

这两个注解是可以同时使用的。

接下来是我的问题:

main方法使用了 @ComponentScan代替@MapperScan,导致报错。

Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'managerService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.admin.mapper.ManagerUser] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.annotation.Resource(shareable=true, mappedName=, description=, name=, type=class java.lang.Object, authenticationType=CONTAINER, lookup=)}

解决:只需要改回@MapperScan即可解决

 

这个报错是 Spring Boot 启动时核心的**Bean 定义加载异常**,根源是 `HouseMapper` 这个 Mapper 接口的 Bean 定义属性 `factoryBeanObjectType` 类型非法(被识别为 String 而非 Class 类型),大概率 MyBatis/MyBatis-Plus 版本与 Spring Boot 版本不兼容、Mapper 注解使用错误或依赖冲突有关。 ### 一、核心原因分析 `factoryBeanObjectType` 是 MyBatis 整合 Spring 时用于标识 Mapper 接口类型的属性,正常情况下应该是 `Class<?>` 类型,报错显示它被解析成了 `String`,常见触发场景: 1. **MyBatis/MyBatis-Plus 版本与 Spring Boot 3.x 不兼容**:Spring Boot 3.x 基于 Spring 6.x,要求 MyBatis 至少 3.0.0+、MyBatis-Plus 至少 3.5.0+,低版本会出现类型解析兼容问题; 2. **Mapper 接口注解错误**:比如混用 `@Mapper` `@Repository`、或注解配置格式错误; 3. **依赖冲突**:项目中同时引入了个版本的 MyBatis/Spring 相关依赖; 4. **Mapper 扫描配置错误**:`@MapperScan` 注解的包路径配置错误,或重复扫描。 ### 二、分步解决方案 #### 步骤 1:检查 MyBatis/MyBatis-Plus 版本(优先级最高) Spring Boot 3.5.9 属于高版本,必须确保 MyBatis/MyBatis-Plus 版本匹配: - **纯 MyBatis**:需使用 `mybatis-spring-boot-starter` 3.0.0+(推荐 3.0.3+); - **MyBatis-Plus**:需使用 `mybatis-plus-boot-starter` 3.5.3+(推荐 3.5.5+)。 修改 `pom.xml` 中的依赖版本: ```xml <!-- 若用 MyBatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> <!-- 关键:必须 3.0.0+ --> </dependency> <!-- 若用 MyBatis-Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.5</version> <!-- 关键:必须 3.5.0+ --> </dependency> ``` #### 步骤 2:检查 HouseMapper 接口的注解 确保 Mapper 接口仅使用 `@Mapper` 注解(不要混用 `@Repository`),示例: ```java package com.example.qngyfwtpt.mapper; import com.example.qngyfwtpt.entity.House; import org.apache.ibatis.annotations.Mapper; // 仅保留这个注解 import java.util.List; @Mapper // 核心注解:标识为 MyBatis Mapper 接口 public interface HouseMapper { // 你的 Mapper 方法 List<House> listAll(); } ``` #### 步骤 3:检查启动类的 Mapper 扫描配置 确保启动类上的 `@MapperScan` 包路径正确,且没有重复扫描: ```java package com.example.qngyfwtpt; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.example.qngyfwtpt.mapper") // 精准指向 Mapper 包,不要包/少包 public class QngyfwtptApplication { public static void main(String[] args) { SpringApplication.run(QngyfwtptApplication.class, args); } } ``` ⚠️ 注意:如果 Mapper 接口已经加了 `@Mapper`,`@MapperScan` 可省略;如果用了 `@MapperScan`,也可以不用给每个 Mapper 加 `@Mapper`,二选一即可,避免重复配置。 #### 步骤 4:清理依赖冲突(若版本匹配后仍报错) 1. 执行 `mvn dependency:tree` 命令,查看依赖树,检查是否有低版本的 `mybatis`/`spring-beans`/`spring-context` 依赖被引入; 2. 排除冲突依赖,示例(若有低版本 MyBatis 被间接引入): ```xml <dependency> <groupId>xxx</groupId> <!-- 其他引入 MyBatis 的依赖 --> <artifactId>xxx</artifactId> <exclusions> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </exclusion> </exclusions> </dependency> ``` #### 步骤 5:清理编译目录并重新构建 1. 执行 `mvn clean` 清空 `target` 目录(删除旧的编译文件); 2. 执行 `mvn compile` 重新编译; 3. 重启 Spring Boot 应用。 ### 三、验证关键点 1. 确认 JDK 版本:Spring Boot 3.5.9 支持 JDK 17+/21,你当前用的 JDK 21.0.9 是兼容的,无需调整; 2. 确认 `application.yml/application.properties` 中 MyBatis 配置正确(比如 mapper-locations 指向 XML 文件,若用注解版可省略): ```yaml mybatis: configuration: map-underscore-to-camel-case: true # 可选,驼峰命名转换 # 若用 XML 版 Mapper,需指定路径 # mapper-locations: classpath:mapper/*.xml ``` ### 四、常见避坑点 - 不要同时引入 `mybatis-spring-boot-starter` `mybatis-plus-boot-starter`(二选一); - 不要在 Mapper 接口上添加 `@Component`/`@Repository`(MyBatis 的 `@Mapper` 已足够,Spring 6.x 对注解类型校验更严格); - Spring Boot 3.x 不再支持 `javax.*` 包,需用 `jakarta.*` 替代(但此报错这个无关,仅提醒)。 按以上步骤调整后,`houseMapper` 的 Bean 定义就能被正确解析,启动异常即可解决。如果仍报错,可补充 `pom.xml` 中 MyBatis 相关依赖代码,我帮你精准排查版本冲突
最新发布
12-25
在 Spring Boot 项目中,如果你在**启动类上使用了 `@Import` 导入了一个配置类**,而这个配置类中又使用了 `@MapperScan` 来扫描 Mapper 接口(尤其是用于配置**数据源**),**通常不会直接冲突**,但**确实需要注意一些关键点**,否则可能导致 Mapper 接口扫描不到、注入失败等问题。 --- ### ✅ 情况说明 #### 启动类结构示例: ```java @SpringBootApplication @Import(MyDataSourceConfig.class) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` #### 配置类结构示例: ```java @Configuration @MapperScan(basePackages = "com.example.mapper.ds1", sqlSessionTemplateRef = "ds1SqlSessionTemplate") public class MyDataSourceConfig { // 数据源配置代码... } ``` --- ### ✅ 是否会冲突? #### ✅ 正常情况下 **不会冲突**,但要注意以下几点: | 问题点 | 说明 | 解决方法 | |--------|------|----------| | 包路径扫描冲突 | 如果个 `@MapperScan` 扫描的包路径有重叠,可能会导致某些接口被绑定到错误的 `SqlSessionTemplate` | 使用 `sqlSessionTemplateRef` 明确指定每个 `@MapperScan` 使用的模板 | | Mapper 接口未被正确扫描 | 如果 `@MapperScan` 的包路径写错,或接口不在扫描路径下 | 检查包路径是否正确 | | 个 `@MapperScan` 未配合 `@Configuration` | 如果配置类没有加 `@Configuration`,可能导致配置未生效 | 确保配置类加上 `@Configuration` | | 启动类上的 `@MapperScan` 配置类上的冲突 | 如果启动类本身也加了 `@MapperScan`,可能导致扫描路径冲突 | 建议统一在配置类中管理扫描逻辑 | --- ### ✅ 数据源下推荐做法 #### ✅ 示例:两个数据源,两个 `@MapperScan` ```java @Configuration @MapperScan(basePackages = "com.example.mapper.ds1", sqlSessionTemplateRef = "ds1SqlSessionTemplate") public class DataSource1Config { // ds1 的 SqlSessionFactory、SqlSessionTemplate 配置 } @Configuration @MapperScan(basePackages = "com.example.mapper.ds2", sqlSessionTemplateRef = "ds2SqlSessionTemplate") public class DataSource2Config { // ds2 的 SqlSessionFactory、SqlSessionTemplate 配置 } ``` 然后在启动类中 `@Import` 这两个配置类: ```java @SpringBootApplication @Import({DataSource1Config.class, DataSource2Config.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` --- ### ✅ 总结:是否会导致找不到类? | 情况 | 是否会导致找不到类 | |------|-------------------| | `@MapperScan` 包路径正确、配置合理 | ❌ 不会 | | 个 `@MapperScan` 路径重叠、但使用了不同 `sqlSessionTemplateRef` | ❌ 不会 | | 包路径错误、或配置类未加 `@Configuration` | ✅ 可能导致找不到类 | | 启动类配置类都加了 `@MapperScan` 并扫描了相同路径 | ✅ 可能导致冲突或注入失败 | --- ### ✅ 建议最佳实践 1. **统一管理 Mapper 扫描**:建议将 `@MapperScan` 放在配置类中,而不是启动类上。 2. **使用 `@Import` 导入配置类**:确保数据源配置类被正确加载。 3. **使用 `sqlSessionTemplateRef` 分离数据源**:避免不同数据源的 Mapper 混用。 4. **检查日志输出**:Spring 启动时查看 Mapper 接口是否被正确注册为 Bean。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值