为何Spring Boot偶发无法找到@Autowired对应类Bean的异常?
@SpringBootApplication 注解本身已经集成了@ComponentScan、@SpringBootConfiguration、@EnableAutoConfiguration三个核心注解,默认扫描规则为:
- 扫描启动类所在包及其所有子包下,标注了
@Component、@Service、@RestController、@Repository等注解的类,注册为Spring容器的bean - Spring Data JPA的自动配置会默认扫描同包下继承了JpaRepository的接口,自动生成代理实现类注册到容器,正常情况下不需要额外加
@ComponentScan或@EnableJpaRepositories注解。
你遇到的报错核心原因如下:
1. 实体类主键注解导入错误
你提供的Admin实体类中,@Id注解导入的是org.springframework.data.annotation.Id,这是Spring Data项目的通用主键注解,JPA规范要求的实体主键注解必须是javax.persistence.Id(适配Spring Boot 2.x版本)或者jakarta.persistence.Id(适配Spring Boot 3.x及以上版本)。这个错误会导致JPA无法识别Admin为合法的持久化实体,Spring Data JPA在生成AdminRepository的代理实现类时会直接跳过,因此容器中不存在对应类型的bean,触发启动报错。
2. Spring Boot版本不兼容
如果你最近新建的项目使用的是Spring Boot 3.x及以上版本,原来javax.persistence包下的所有JPA注解已经全部迁移到jakarta.persistence包下,你代码中用到的javax.persistence.Entity、javax.persistence.GeneratedValue等注解在新版本中不会被JPA扫描识别,同样会导致实体校验失败,Repository无法生成。
为什么加了@ComponentScan后能正常启动?
你当前添加的@ComponentScan(basePackages = {"com.example.demo.repository"})本身并不能解决JPA Repository的生成问题,反而会覆盖@SpringBootApplication的默认扫描规则:你只指定了扫描repository包,那么controller、service包下的@RestController、@Service注解的类默认不会被扫描,正常应该会触发找不到AdminService的错误。你添加该注解后能正常启动,大概率是你添加注解的同时无意间修正了实体类的注解错误,或者项目中存在其他未提供的配置类补充了扫描范围。
- 修正实体类的注解导入:
- 若使用Spring Boot 2.x版本:将实体类中
import org.springframework.data.annotation.Id;替换为import javax.persistence.Id; - 若使用Spring Boot 3.x及以上版本:将所有
javax.persistence开头的导入全部替换为jakarta.persistence开头,包括@Entity、@Id、@GeneratedValue等注解
- 若使用Spring Boot 2.x版本:将实体类中
- 移除启动类上自定义的
@ComponentScan注解,恢复@SpringBootApplication的默认扫描规则 - 确认项目依赖中已经引入
spring-boot-starter-data-jpa,且启动类没有排除JpaRepositoriesAutoConfiguration自动配置类
内容的提问来源于stack exchange,提问作者Java Programmer

