返回 元婴・灵宝秘藏

Spring Boot 最常用100个注解终极详解(典藏版)

博主
大约 22 分钟

Spring Boot 最常用100个注解终极详解(典藏版)

本文目标:提供一份完整、详细、可收藏的Spring Boot注解大全。涵盖六大核心领域的100个常用注解,每个注解都配有详细的功能解析、使用场景、核心要点,并用加粗标注重点。文末附赠10道高频面试题和10道实战场景题,助你彻底掌握。

阅读提示:注解按领域分类,可直接跳转查阅。加粗文字为必须掌握的核心要点。


📚 一、核心容器(IoC与配置)· 20个

序号注解详细解析与重点
1@SpringBootApplication组合注解,包含 @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan。标注在主启动类上,表示这是一个Spring Boot应用。重点:它会自动扫描主类所在包及其子包下的所有组件。
2@Configuration标注在类上,表明该类是一个 配置类,相当于传统的XML配置文件。类中可以定义多个 @Bean 方法。重点:配置类本身也会被Spring容器管理。
3@EnableAutoConfiguration开启自动配置,Spring Boot会根据项目依赖的jar包自动配置Spring应用。例如,引入spring-boot-starter-web会自动配置Tomcat和Spring MVC。底层原理:通过 @Import(AutoConfigurationImportSelector.class) 加载 META-INF/spring.factories 中的自动配置类。
4@ComponentScan定义组件扫描路径,默认扫描主类所在包及其子包。可以自定义扫描包:@ComponentScan("com.example")重点:如果定义的Bean扫描不到,检查该注解是否覆盖了正确包路径。
5@Component最通用的Spring组件注解,被标注的类会被自动注册为Bean。重点:它是所有特定组件注解(如@Service)的元注解。
6@Service标注业务逻辑层的类,是 @Component 的语义化特例。重点:虽然没有额外功能,但推荐使用以明确层次。
7@Repository标注数据访问层的类。除了注册Bean外,Spring还会自动将其抛出的持久层异常(如SQLException)转换为Spring的DataAccessException重点:具有异常转换功能。
8@Controller标注控制层(Spring MVC控制器),通常返回视图页面(如Thymeleaf)。重点:若想返回JSON,需配合@ResponseBody使用。
9@RestController组合注解,等于 @Controller + @ResponseBody。用于构建RESTful API,所有方法默认返回JSON/XML数据。重点:前后端分离项目中最常用的注解。
10@Bean标注在方法上,将方法的返回值注册为一个Spring Bean。通常与@Configuration配合使用,用于引入第三方库组件重点:方法名默认为Bean的名称,可通过name属性指定。
11@Autowired按类型(byType)自动装配依赖,是Spring最核心的DI注解。重点:当同一类型存在多个Bean时,需配合@Qualifier指定名称;也可标注在构造器上实现构造器注入(推荐)。
12@Qualifier配合 @Autowired 使用,当同一类型有多个Bean时,按名称指定具体注入哪个。重点:名称是@Bean的方法名或@Component的value值。
13@ResourceJSR-250标准注解,默认**按名称(byName)**装配,是@Autowired的替代方案。可通过name属性指定名称,若找不到名称,再按类型装配。重点:属于Java原生注解,与Spring解耦。
14@Primary当同一类型有多个Bean时,标注此注解的Bean拥有最高优先级,优先被@Autowired注入。重点:用于解决多Bean冲突,类似“首选”Bean。
15@Scope定义Bean的作用域。常用取值:singleton(单例,默认)、prototype(原型)、request(请求)、session(会话)。重点:单例Bean在容器启动时创建,原型Bean每次获取时创建。
16@Lazy针对单例Bean,默认在启动时创建,加上此注解后,改为第一次使用时才创建重点:可用于减少启动时间或解决循环依赖。
17@Value从配置文件(application.properties/yml)中注入单个值,支持SpEL表达式(如#{...})。重点:可用于注入字符串、整数、布尔等基本类型。
18@ConfigurationProperties批量绑定配置文件中的属性(如指定prefix="app")到一个Java Bean上,支持复杂类型(List、Map)和数据校验(结合@Validated)。重点:比@Value更适合管理一组相关配置。
19@PropertySource用于指定要加载的外部配置文件,如@PropertySource("classpath:custom.properties")重点:通常与@Configuration配合使用,将自定义属性加载到环境变量中。
20@Profile指定Bean或配置在特定的环境(如devtestprod)中才生效。重点:通过spring.profiles.active激活环境,实现多环境配置隔离。

🌐 二、Web开发(MVC与REST)· 20个

序号注解详细解析与重点
21@RequestMapping映射HTTP请求路径到控制器方法。可通过method属性指定请求类型(GET、POST等),也可标注在类上定义父路径。重点:是最基础的请求映射注解,但日常推荐用简化版本。
22@GetMapping组合注解,等于 @RequestMapping(method = RequestMethod.GET),处理GET请求。重点:语义清晰,推荐使用。
23@PostMapping处理POST请求,常用于创建资源。
24@PutMapping处理PUT请求,常用于更新资源。
25@DeleteMapping处理DELETE请求,常用于删除资源。
26@PatchMapping处理PATCH请求,用于部分更新资源。
27@PathVariable获取URL路径模板中的变量,如 /users/{id} 中的 id重点:如果参数名与路径变量名不一致,需用value指定。
28@RequestParam获取请求参数(URL中的 ?key=value 或表单数据application/x-www-form-urlencoded)。可设置requireddefaultValue重点:常用于GET请求的分页、过滤参数。
29@RequestBody接收请求体中的JSON/XML数据,并将其绑定到Java对象上。重点:一个请求只能有一个@RequestBody,且需要HttpMessageConverter支持(Spring Boot默认支持Jackson)。
30@ResponseBody将方法返回值直接写入HTTP响应体(通常是JSON),而非解析为视图路径。重点@RestController已包含此注解,无需重复标注。
31@RequestHeader获取指定的请求头信息,如 @RequestHeader("User-Agent") String userAgent
32@CookieValue获取指定的Cookie值,如 @CookieValue("JSESSIONID") String sessionId
33@SessionAttribute从HTTP Session 中获取指定的属性值(通常用于获取之前存入Session的数据)。
34@RequestAttribute获取请求域(request scope)中的属性(通常由过滤器或拦截器设置)。
35@ModelAttribute将方法参数或返回值绑定到Model中,供视图渲染使用。也可用于在控制器方法执行前加载通用数据。重点:在参数上使用时,Spring会自动将请求参数绑定到该对象。
36@SessionAttributes将Model中的指定属性临时存储到Session中,实现跨请求共享(如购物车数据)。重点:标注在类上,指定属性名。
37@CrossOrigin开启跨域访问支持,可标注在类或方法上。可指定originsmethods等属性。重点:解决前后端分离开发中的跨域问题。
38@ControllerAdvice全局控制器增强,常配合@ExceptionHandler做全局异常处理,也可配合@InitBinder实现全局数据绑定。重点:被标注的类会被扫描并应用于所有@Controller
39@RestControllerAdvice组合注解,等于 @ControllerAdvice + @ResponseBody。用于处理全局异常并返回JSON数据,是REST API的最佳实践。
40@ExceptionHandler标注在方法上,声明该方法用于处理指定类型的异常。通常放在@ControllerAdvice类中,实现统一异常处理。重点:可以返回视图或JSON。

💾 三、数据访问(JPA/MyBatis/事务)· 25个

序号注解详细解析与重点
41@Transactional声明式事务管理的核心,标注在类或方法上,开启数据库事务。重点:注意失效场景(非public、内部调用、异常被捕获、异常类型不匹配)。可通过propagationisolationrollbackFor等属性精细控制。
42@EntityJPA注解,标识一个JPA实体类,与数据库表映射。重点:需要有无参构造器。
43@Table指定实体类对应的数据库表名(当表名与类名不同时使用)。如@Table(name = "t_user")
44@IdJPA注解,标注实体类的主键字段。
45@GeneratedValue配置主键的生成策略,如strategy = GenerationType.IDENTITY(自增)、SEQUENCEAUTO
46@Column映射实体字段与数据库表的列名(当字段名与列名不同时)。也可指定长度、是否可为空等属性。
47@Transient标注该字段不参与数据库表字段的映射,即忽略该字段。
48@Temporal用于配置java.util.DateCalendar类型的字段在数据库中的精度(DATE、TIME、TIMESTAMP)。
49@OneToOneJPA实体关系注解,标识一对一关联。常用属性:cascade(级联操作)、fetch(加载策略)、mappedBy(被拥有方指向拥有方)。
50@OneToMany标识一对多关联。常用属性:mappedBy(指向多方的关联字段)、cascadefetch
51@ManyToOne标识多对一关联(最常用)。通常配合@JoinColumn指定外键列。重点:默认fetch = FetchType.EAGER(立即加载),注意N+1问题。
52@ManyToMany标识多对多关联。常与@JoinTable指定中间表。
53@JoinColumn指定关联表之间的外键列名。常与@ManyToOne@OneToOne配合使用。
54@JoinTable用于多对多关系,指定中间连接表的信息,包括表名、关联列等。
55@QueryJPA中定义自定义查询(JPQL或原生SQL)。重点:使用@Query("select u from User u where u.name = :name")
56@Modifying@Query配合使用,表示该查询是更新或删除操作,需要触发事务(通常还要加上@Transactional)。
57@EnableJpaRepositories启用JPA仓库,并指定扫描Repository接口的包路径(通常在配置类上使用)。
58@MapperMyBatis注解,标记一个接口为Mapper接口,用于生成SQL映射代理。重点:需要在启动类上添加@MapperScan或在每个接口上加此注解。
59@MapperScan启用MyBatis Mapper扫描,指定扫描接口的包路径(替代在每个接口上加@Mapper)。重点:通常加在启动类或配置类上。
60@SelectMyBatis注解,直接写在接口方法上,定义查询SQL。如@Select("SELECT * FROM user WHERE id = #{id}")
61@Insert定义插入SQL
62@Update定义更新SQL
63@Delete定义删除SQL
64@Options配置MyBatis操作的选项,如获取自增主键值:@Options(useGeneratedKeys = true, keyProperty = "id")
65@Param为MyBatis SQL 中的参数指定名称,尤其是多参数时。如List<User> findByCondition(@Param("name") String name, @Param("age") Integer age)

🔐 四、安全与控制(Spring Security & 条件)· 15个

序号注解详细解析与重点
66@EnableWebSecurity启用Spring Security的Web安全支持,通常与WebSecurityConfigurerAdapter一起使用(Spring Security 5.7+后推荐基于组件的方式)。
67@EnableGlobalMethodSecurity启用方法级别的安全控制,如@PreAuthorize@Secured。常用属性:prePostEnabled = true(启用@PreAuthorize等)、securedEnabled = true(启用@Secured)。
68@PreAuthorize方法执行前进行权限校验,如@PreAuthorize("hasRole('ADMIN')")重点:支持SpEL表达式,功能强大。
69@PostAuthorize方法执行后进行权限校验,常用于校验返回结果(如检查用户是否有权查看该数据)。
70@PreFilter对方法参数进行过滤,通常用于集合参数,过滤掉不符合权限的元素。
71@PostFilter对方法返回的集合进行过滤,返回给调用者前剔除不符合权限的元素。
72@Secured基于角色的访问控制(较老的方式),如@Secured("ROLE_ADMIN")重点:只能使用角色名,不支持表达式。
73@RolesAllowedJSR-250标准,作用和@Secured类似,但属于Java EE标准。
74@AuthenticationPrincipal在Controller参数中获取当前认证用户详情。如public String getInfo(@AuthenticationPrincipal UserDetails userDetails)
75@ConditionalSpring底层条件注解的基础,根据条件决定是否加载Bean。开发者可以实现Condition接口自定义条件。
76@ConditionalOnClass当类路径下存在指定类时,配置生效。常用于自动配置。
77@ConditionalOnMissingClass当类路径下不存在指定类时,配置生效。
78@ConditionalOnBean当容器中存在指定Bean时,配置生效。
79@ConditionalOnMissingBean当容器中不存在指定Bean时,配置生效(常用于覆盖默认配置)。
80@ConditionalOnProperty根据配置文件中的属性值决定是否加载。如@ConditionalOnProperty(name = "my.feature.enabled", havingValue = "true"),实现功能开关。

⚡ 五、异步与任务调度 · 10个

序号注解详细解析与重点
81@EnableAsync开启Spring的异步方法执行能力。通常在配置类或启动类上添加。
82@Async标注方法为异步方法,调用后会立即返回,实际逻辑在线程池中执行。重点:需要配合@EnableAsync使用;注意内部调用失效;建议自定义线程池。
83@EnableScheduling开启Spring的定时任务支持。
84@Scheduled标注方法为定时任务,支持cron表达式、fixedRatefixedDelay等。重点:默认使用单线程池执行,长任务会阻塞其他任务;建议自定义TaskScheduler
85@EnableJms开启对JMS(Java消息服务)的支持,用于消息队列。
86@JmsListener标注方法为JMS消息的监听器,当消息到达时自动调用。
87@EnableRabbit开启对RabbitMQ的支持。
88@RabbitListener标注方法为RabbitMQ消息的监听器
89@KafkaListener标注方法为Kafka消息的监听器
90@EnableWebSocket开启对WebSocket的支持,用于实时通信。

🧪 六、测试与扩展 · 10个

序号注解详细解析与重点
91@SpringBootTest启动完整的Spring Boot应用上下文进行集成测试。重点:会加载所有Bean,适合整体功能测试。
92@WebMvcTest切片测试,仅加载Web层(Controller)相关Bean,用于Controller层单元测试。重点:需要配合@MockBean模拟Service层。
93@DataJpaTest切片测试,仅加载JPA相关组件(如@Repository),用于Repository层测试。默认使用嵌入式数据库。
94@JsonTest切片测试,仅加载JSON相关组件(如Jackson),用于测试JSON序列化/反序列化。
95@MockBean在测试上下文中,为指定的Bean创建并注入一个Mock对象(基于Mockito)。重点:用于替换真实Bean,隔离依赖。
96@SpyBean在测试上下文中,创建并注入一个Spy对象(部分模拟),真实方法会被调用,但可以验证或存根。
97@Sql在测试方法执行前后,执行指定的SQL脚本初始化或清理数据。可指定executionPhase(前/后)。
98@DirtiesContext标记测试方法或类会 “污染” 应用上下文,执行后Spring会重新加载上下文。用于测试对上下文有副作用的操作。
99@EnableSwagger2启用Swagger 2 在线接口文档(已过时,新项目推荐使用SpringDoc OpenAPI)。
100@ApiOperationSwagger注解,标注在方法上,描述一个API接口的用途和参数。

📝 附录:10道高频面试题 + 10道实战场景题

面试题精选(含答案)

1. 问:@SpringBootApplication 中的 @EnableAutoConfiguration 是如何实现自动配置的?

答: @EnableAutoConfiguration 通过 @Import(AutoConfigurationImportSelector.class) 导入一批自动配置类。AutoConfigurationImportSelector 会扫描所有jar包下的 META-INF/spring.factories(或2.7后的 AutoConfiguration.imports)文件,将其中的 XxxAutoConfiguration 类加载为候选配置。这些候选类上通常带有 @ConditionalOnXxx 注解,只有当条件满足(如存在对应的类、Bean或配置属性)时,该自动配置类才会真正生效,从而完成自动配置。

2. 问:@Autowired@Resource 在注入时的核心区别是什么?

答: 区别有三点:

  • 来源不同@Autowired 是Spring定义的,@Resource 是JSR-250标准(Java EE)定义的。
  • 装配方式不同@Autowired 默认**按类型(byType)装配;@Resource 默认按名称(byName)**装配,如果找不到名称,则回退为按类型装配。
  • 解决冲突的方式不同:当同一类型有多个Bean时,@Autowired 需配合 @Qualifier 按名称指定;@Resource 可通过 name 属性直接指定名称。

3. 问:@Transactional 注解在哪些典型场景下会失效?

答: 常见失效场景:

  • 非public方法@Transactional 标注在非public方法上,Spring无法生成代理,事务失效。
  • 同类内部调用:同一个类中的方法A(无事务)调用方法B(有@Transactional),由于调用的是this对象(原始对象)而非代理对象,事务拦截器无法生效。
  • 异常被捕获且未抛出:在方法内用try-catch捕获了异常,但没有抛出,Spring无法感知异常,不会回滚。
  • 异常类型不匹配:默认只回滚RuntimeExceptionError,如果抛出的是受检异常(如IOException),事务不会回滚。可通过rollbackFor = Exception.class解决。
  • 数据库引擎不支持事务:如MySQL的MyISAM引擎不支持事务。

4. 问:@Configuration 注解的 proxyBeanMethods = false 有什么作用?

答: 设置proxyBeanMethods = false开启 Lite 模式。在Lite模式下,配置类不会被CGLIB代理,@Bean方法调用不会经过代理拦截,每次调用都会返回一个新的对象(如果方法内有new操作)。优点是启动速度更快、开销更小,适合配置类内部没有@Bean方法互相调用的场景。默认是true(Full模式),保证单例Bean的依赖关系。

5. 问:@PostConstruct@Autowired 的执行顺序是怎样的?

答: 顺序是:构造方法 → @Autowired(属性注入) → @PostConstruct(初始化前回调)。因此,在构造方法中无法使用被@Autowired注入的Bean,而在@PostConstruct方法中可以安全使用。

6. 问:@ConditionalOnMissingBean 注解在自动配置中扮演什么角色?

答: 它是实现 “用户自定义覆盖默认配置” 的关键。例如在RedisAutoConfiguration中,先判断容器中是否存在RedisTemplate Bean,如果不存在(即用户没有自定义),@ConditionalOnMissingBean(RedisTemplate.class)条件成立,自动配置类才会创建默认的RedisTemplate Bean。这样既保证了开箱即用,又允许用户自定义覆盖。

7. 问:@RequestBody@RequestParam 都可以接收参数,它们的底层实现有何不同?

答: @RequestParamHttpServletRequestgetParameterMap() 获取值,处理的是application/x-www-form-urlencoded编码的请求体或URL参数。@RequestBody 通过 HttpMessageConverterrequest.getInputStream() 中读取请求体字节流,并根据Content-Type(如application/json)将其反序列化为Java对象。

8. 问:@RestControllerAdvice 为什么能处理全局异常?

答: 因为@RestControllerAdvice@Component标注,会被Spring扫描并注册为Bean。Spring MVC在初始化时,会从容器中查找所有带有@ControllerAdvice@RestControllerAdvice的Bean,提取其中用@ExceptionHandler标注的方法,将其注册为全局异常处理器,当控制器抛出异常时,就会调用这些方法。

9. 问:@Async 方法默认使用的线程池有什么问题?应该如何改进?

答: 默认使用SimpleAsyncTaskExecutor,它不是真正的线程池,每次执行都会创建新线程,在高并发下可能导致资源耗尽。改进:在配置类中自定义一个TaskExecutor Bean,如ThreadPoolTaskExecutor,设置核心线程数、最大线程数、队列容量等参数。

10. 问:@Scheduled 定时任务如果执行时间过长,会有什么后果?

答: 默认情况下,所有@Scheduled任务共用一个单线程的调度器。如果一个任务执行时间过长,会阻塞后续所有定时任务的准时执行,导致任务堆积或延迟。解决方法:自定义一个TaskScheduler Bean,配置合适的线程池大小(如ThreadPoolTaskScheduler),让不同任务可以并发执行。


实战场景题(含思路)

1. 场景:项目启动时需要从数据库加载配置到Redis缓存。

思路: 创建一个@Component类,在@PostConstruct方法中注入Service查询数据库,然后将数据存入Redis。@PostConstruct保证在Bean初始化完成后立即执行。

2. 场景:自定义Starter,希望用户配置 my.service.enabled=true 时才加载Bean。

思路: 在自动配置类上使用@ConditionalOnProperty(name = "my.service.enabled", havingValue = "true"),这样只有当配置文件中该属性为true时,配置类才会生效。

3. 场景:Service层内部方法调用 @Transactional 方法,事务不生效。

思路: 内部调用失效,需通过代理对象调用。方案一:将两个方法拆分到不同的Service类中。方案二:在当前类中注入自己的代理(@Autowired private UserService self;),然后用self.methodB()调用。方案三:启用@EnableAspectJAutoProxy(exposeProxy = true),然后用AopContext.currentProxy()获取代理对象。

4. 场景:想要统计每个Controller方法的执行时间,不侵入业务代码。

思路: 定义一个@Aspect切面,使用@Around("@within(org.springframework.web.bind.annotation.RestController)")作为切点,环绕通知中记录开始时间,执行方法,再记录结束时间并打印耗时。

5. 场景:想把配置文件中的 custom.upload.path 注入到一个工具类的静态变量中。

思路: @Value不能直接注入静态变量。可在工具类中提供一个非静态的setter方法,标注@Value,然后将值赋给静态变量。

@Component
public class FileUtil {
    private static String uploadPath;
    @Value("${custom.upload.path}")
    public void setUploadPath(String path) {
        FileUtil.uploadPath = path;
    }
}

6. 场景:开发和生产环境需要配置不同的数据源。

思路: 使用@Profile注解。分别定义两个配置类或两个@Bean方法,一个标注@Profile("dev"),另一个标注@Profile("prod")。然后在不同环境中通过spring.profiles.active激活对应profile。

7. 场景:应用启动报错 Consider defining a bean of type 'XxxService' in your configuration.

思路: 这是Bean未定义的错误。排查步骤:1. 检查XxxService类上是否有@Service@Component注解。2. 检查该类是否在主启动类的子包下,确保被@ComponentScan扫描到。3. 如果是通过@Bean配置,检查配置类是否被扫描或导入。

8. 场景:想写一个通用的Redis操作组件 RedisUtils,交给Spring管理。

思路: 创建一个@Configuration类,在里面定义一个@Bean方法返回RedisUtils实例。方法参数可以自动注入StringRedisTemplate等依赖。

@Configuration
public class RedisConfig {
    @Bean
    public RedisUtils redisUtils(StringRedisTemplate redisTemplate) {
        return new RedisUtils(redisTemplate);
    }
}

9. 场景:前端传参字段名是 user-name,后端实体类是 userName,接收不到值。

思路: 在Controller方法参数前使用@RequestParam("user-name")显式映射;或在使用@RequestBody的实体类字段上加@JsonProperty("user-name")注解(Jackson)。

10. 场景:单元测试时只想测试Controller层,不想加载整个Spring上下文。

思路: 使用@WebMvcTest(YourController.class)注解,它只会加载Web层相关组件。对于Service层依赖,用@MockBean创建Mock对象并模拟其行为,实现Controller层的独立单元测试。


结语:本文梳理了Spring Boot最常用的100个注解,并深入讲解了核心注解的底层原理。希望这份清单能成为你开发路上的得力助手。掌握这些注解,你就掌握了Spring Boot开发的精髓。

知识点测试

读完文章了?来测试一下你对知识点的掌握程度吧!

评论区

使用 GitHub 账号登录后即可发表评论,支持 Markdown 格式。

如果评论系统无法加载,请确保:

  • 您的网络可以访问 GitHub
  • giscus GitHub App 已安装到仓库
  • 仓库已启用 Discussions 功能