作为 Java 后端开发者,Spring 全家桶的注解是我们每天都在使用的工具。从@Service、@Autowired到@RestController、@SpringBootApplication,这些注解大大简化了我们的开发工作,让我们从繁琐的 XML 配置中解放出来。
但很多开发者只是机械地使用这些注解,却不知道它们的作用和原理。这导致我们在遇到注解不生效、依赖注入失败、事务失效等问题时,往往无从下手。同时,这些注解也是面试中 100% 会被问到的基础考点。
这篇文章,我整理了Spring、Spring Boot、Spring MVC 中最常用的 30 + 个注解 ,按照功能分类,每个注解都包含作用、用法、代码示例和注意事项。看完这篇,你不仅能正确使用这些注解,更能理解它们的底层原理,轻松应对所有相关面试题。

一、先理清:三个框架的关系
在开始之前,我们先理清 Spring、Spring Boot、Spring MVC 三个框架的关系:
- Spring:核心框架,提供了 IoC、AOP、事务管理等基础功能
- Spring MVC:Spring 的 Web 模块,基于 Servlet 实现的 MVC 框架,用于开发 Web 应用
- Spring Boot:Spring 的快速开发脚手架,基于 "约定大于配置" 的思想,简化了 Spring 应用的配置和部署
简单来说:Spring 是基础,Spring MVC 是 Web 扩展,Spring Boot 是快速开发工具。它们的注解是通用的,只是 Spring Boot 提供了更多自动配置相关的注解。
二、核心组件注解(Spring 通用)
这些注解是 Spring 最基础也是最常用的注解,用于定义和管理 Bean。
1. @Component & 派生注解
这是最核心的组件注解,用于将类标记为 Spring 容器中的 Bean。
@Component
作用 :通用组件注解,将任意类标记为 Spring 容器中的 Bean。 使用场景:不属于业务层、数据访问层或控制层的通用组件。
java
@Component
public class CommonUtils {
// 通用工具类
}
派生注解
Spring 提供了三个@Component的派生注解,语义更明确,推荐优先使用:
| 注解 | 作用 | 使用场景 |
|---|---|---|
@Service |
标记业务层组件 | 业务逻辑处理类 |
@Repository |
标记数据访问层组件 | DAO/Mapper 接口实现类 |
@Controller |
标记控制层组件 | Spring MVC 控制器 |
代码示例:
java
// 业务层
@Service
public class UserService {
// 业务逻辑
}
// 数据访问层
@Repository
public class UserDao {
// 数据库操作
}
// 控制层
@Controller
public class UserController {
// 请求处理
}
注意:虽然这四个注解在功能上几乎没有区别,但使用语义明确的注解可以让代码结构更清晰,也便于 Spring 后续版本进行增强。
2. @Configuration & @Bean
用于定义配置类和注册 Bean。
@Configuration
作用:标记一个类为配置类,替代 XML 配置文件。
注意:配置类本身也会被 Spring 容器管理。
@Bean
作用:在配置类中注册一个 Bean,方法返回值就是 Bean 的实例。
使用场景:注册第三方库的对象,或者需要复杂初始化逻辑的 Bean。
java
@Configuration
public class AppConfig {
// 注册一个名为"redisTemplate"的Bean
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 复杂的初始化逻辑
return template;
}
}
@Bean vs @Component:
@Component用于标记自己写的类@Bean用于注册第三方库的类,或者需要复杂初始化的类
3. @Scope
作用 :指定 Bean 的作用域。 默认值 :singleton(单例)。
常用作用域:
| 作用域 | 含义 |
|---|---|
singleton |
单例,整个应用生命周期内只有一个实例 |
prototype |
原型,每次获取都创建一个新的实例 |
request |
每个 HTTP 请求创建一个实例(Web 环境) |
session |
每个会话创建一个实例(Web 环境) |
java
// 原型Bean,每次获取都创建新实例
@Service
@Scope("prototype")
public class PrototypeService {
}
4. @PostConstruct & @PreDestroy
作用:Bean 生命周期回调注解,在 Bean 初始化和销毁时执行。
java
@Service
public class UserService {
@PostConstruct
public void init() {
// Bean初始化完成后执行
System.out.println("UserService初始化完成");
}
@PreDestroy
public void destroy() {
// Bean销毁前执行
System.out.println("UserService即将销毁");
}
}
执行顺序 :构造方法 → 依赖注入 → @PostConstruct → 初始化方法 → @PreDestroy
5. @Lazy
作用:延迟加载 Bean,只有在第一次使用时才创建实例。
默认值 :false(立即加载)。
java
// 延迟加载,只有在第一次注入或getBean时才创建
@Service
@Lazy
public class LazyService {
}
使用场景:
- 初始化耗时较长的 Bean
- 很少使用的 Bean
- 解决循环依赖问题
三、依赖注入注解
这些注解用于注入 Bean 之间的依赖关系。
1. @Autowired
作用:按类型自动注入依赖。
默认行为:必须存在对应的 Bean,否则抛出异常。
java
@Service
public class UserService {
// 字段注入(不推荐)
@Autowired
private UserDao userDao;
// 构造方法注入(推荐)
private final OrderService orderService;
// Spring 4.3以后,单构造方法可以省略@Autowired
public UserService(OrderService orderService) {
this.orderService = orderService;
}
// setter方法注入
private LogService logService;
@Autowired
public void setLogService(LogService logService) {
this.logService = logService;
}
}
最佳实践:优先使用构造方法注入,保证依赖不可变,便于单元测试。
2. @Resource
作用:按名称自动注入依赖,是 JSR-250 标准注解。
默认行为:先按名称注入,找不到再按类型注入。
java
@Service
public class UserService {
// 按名称注入名为"userDao"的Bean
@Resource
private UserDao userDao;
}
3. @Autowired vs @Resource
这是面试最常考的问题之一,两者的核心区别:
| 特性 | @Autowired |
@Resource |
|---|---|---|
| 来源 | Spring 框架 | JSR-250 标准 |
| 注入方式 | 默认按类型注入 | 默认按名称注入 |
| 支持的注入点 | 字段、setter 方法、构造方法 | 字段、setter 方法 |
| 必须性 | 默认必须存在 | 默认必须存在 |
使用建议 :Spring 项目优先使用@Autowired,需要按名称注入时使用@Resource或@Autowired + @Qualifier。
4. @Qualifier
作用:当有多个相同类型的 Bean 时,指定要注入的 Bean 名称。
java
// 两个相同类型的Bean
@Service("userService1")
public class UserService1 implements UserService {
}
@Service("userService2")
public class UserService2 implements UserService {
}
// 注入时指定名称
@Service
public class OrderService {
@Autowired
@Qualifier("userService1")
private UserService userService;
}
5. @Value
作用:注入配置文件中的属性值。
java
@Service
public class UserService {
// 注入简单值
@Value("${app.name:默认值}")
private String appName;
// 注入整数
@Value("${app.port:8080}")
private int port;
// 注入布尔值
@Value("${app.debug:false}")
private boolean debug;
}
配置文件 application.yml:
java
app:
name: 我的应用
port: 8080
debug: true
四、Spring MVC Web 注解
这些注解用于开发 Web 应用,处理 HTTP 请求。
1. @Controller & @RestController
用于标记控制器类。
@Controller
作用:标记一个类为 Spring MVC 控制器,返回视图名称。
使用场景:传统的服务端渲染页面的应用。
@RestController
作用 :组合注解,相当于@Controller + @ResponseBody,返回 JSON/XML 数据。
使用场景:前后端分离的 RESTful API 开发。
java
// 返回JSON数据的控制器
@RestController
@RequestMapping("/api/users")
public class UserController {
// 请求处理方法
}
2. @RequestMapping & 派生注解
用于映射 HTTP 请求到处理方法。
@RequestMapping
作用:通用的请求映射注解,可以指定请求方法、路径、参数等。
派生注解(推荐使用)
Spring 4.3 以后引入了更简洁的派生注解,对应不同的 HTTP 方法:
| 注解 | 作用 | 对应 HTTP 方法 |
|---|---|---|
@GetMapping |
处理 GET 请求 | GET |
@PostMapping |
处理 POST 请求 | POST |
@PutMapping |
处理 PUT 请求 | PUT |
@DeleteMapping |
处理 DELETE 请求 | DELETE |
@PatchMapping |
处理 PATCH 请求 | PATCH |
java
@RestController
@RequestMapping("/api/users")
public class UserController {
// GET /api/users
@GetMapping
public List<User> listUsers() {
return userService.list();
}
// GET /api/users/1
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id);
}
// POST /api/users
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
// PUT /api/users/1
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user);
}
// DELETE /api/users/1
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
}
3. @RequestParam
作用:获取 URL 查询参数或表单参数。
java
// GET /api/users?name=张三&age=20
@GetMapping("/api/users")
public List<User> listUsers(
@RequestParam String name,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return userService.list(name, page, size);
}
4. @PathVariable
作用:获取 URL 路径中的变量。
java
// GET /api/users/1
@GetMapping("/api/users/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id);
}
5. @RequestParam vs @PathVariable
| 特性 | @RequestParam |
@PathVariable |
|---|---|---|
| 作用 | 获取查询参数 | 获取路径变量 |
| 位置 | URL? 后面的参数 | URL 路径中的变量 |
| 示例 | /api/users?name=张三 |
/api/users/1 |
| 可选性 | 默认必须,可以设置 required=false | 默认必须 |
6. @RequestBody & @ResponseBody
@RequestBody
作用:将 HTTP 请求体中的 JSON/XML 数据绑定到 Java 对象。
@ResponseBody
作用:将方法返回值序列化为 JSON/XML 数据,写入 HTTP 响应体。
java
// 请求体JSON自动绑定到User对象
@PostMapping("/api/users")
public User createUser(@RequestBody User user) {
return userService.save(user);
}
注意 :@RestController已经包含了@ResponseBody,所以不需要再单独添加。
7. @RequestHeader & @CookieValue
@RequestHeader
作用:获取 HTTP 请求头中的值。
@CookieValue
作用:获取 Cookie 中的值。
java
@GetMapping("/api/users")
public List<User> listUsers(
@RequestHeader("Authorization") String token,
@CookieValue("sessionId") String sessionId) {
return userService.list();
}
五、Spring Boot 核心注解
这些注解是 Spring Boot 特有的,用于自动配置和快速开发。
1. @SpringBootApplication
作用 :Spring Boot 应用的入口注解,是一个组合注解。 包含的三个核心注解:
@SpringBootConfiguration:标记为 Spring Boot 配置类@EnableAutoConfiguration:开启自动配置@ComponentScan:开启组件扫描,默认扫描主启动类所在的包及其子包
java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2. @EnableAutoConfiguration
作用:开启 Spring Boot 自动配置功能,根据引入的依赖自动配置对应的 Bean。
注意 :@SpringBootApplication已经包含了这个注解,通常不需要单独使用。
3. @ConfigurationProperties
作用 :将配置文件中的属性批量绑定到 Java 对象。 使用场景 :当有多个相关的配置属性时,比@Value更方便。
java
// 绑定以"app"为前缀的配置
@ConfigurationProperties(prefix = "app")
@Component
public class AppProperties {
private String name = "默认应用";
private int port = 8080;
private boolean debug = false;
// getter和setter方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getPort() { return port; }
public void setPort(int port) { this.port = port; }
public boolean isDebug() { return debug; }
public void setDebug(boolean debug) { this.debug = debug; }
}
配置文件 application.yml:
java
app:
name: 我的应用
port: 8080
debug: true
使用:
java
@Service
public class UserService {
@Autowired
private AppProperties appProperties;
public void test() {
System.out.println(appProperties.getName());
System.out.println(appProperties.getPort());
}
}
4. @Conditional 系列
作用:条件注解,根据特定条件决定是否注册 Bean。
常用的条件注解:
| 注解 | 作用 |
|---|---|
@ConditionalOnClass |
当类路径下存在指定的类时注册 Bean |
@ConditionalOnMissingClass |
当类路径下不存在指定的类时注册 Bean |
@ConditionalOnBean |
当容器中存在指定的 Bean 时注册 Bean |
@ConditionalOnMissingBean |
当容器中不存在指定的 Bean 时注册 Bean |
@ConditionalOnProperty |
当配置文件中存在指定的属性时注册 Bean |
java
@Configuration
public class RedisConfig {
// 当类路径下存在RedisTemplate类时注册Bean
@Bean
@ConditionalOnClass(RedisTemplate.class)
@ConditionalOnMissingBean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
return template;
}
}
5. @SpringBootTest
作用:Spring Boot 测试注解,用于启动 Spring 容器进行集成测试。
java
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testGetUserById() {
User user = userService.getById(1L);
assertNotNull(user);
}
}
六、事务管理注解
@Transactional
作用:声明式事务注解,用于标记需要事务管理的方法或类。
使用位置:可以标记在类上(所有方法都有事务)或方法上(只有该方法有事务)。
常用参数:
| 参数 | 作用 | 默认值 |
|---|---|---|
rollbackFor |
指定哪些异常会导致事务回滚 | RuntimeException和Error |
propagation |
事务传播行为 | Propagation.REQUIRED |
isolation |
事务隔离级别 | Isolation.DEFAULT |
timeout |
事务超时时间 | -1(永不超时) |
readOnly |
是否只读事务 | false |
java
@Service
public class UserService {
// 所有异常都回滚
@Transactional(rollbackFor = Exception.class)
public void transfer(String from, String to, int amount) {
// 扣减A的余额
accountMapper.decreaseBalance(from, amount);
// 增加B的余额
accountMapper.increaseBalance(to, amount);
}
}
注意 :@Transactional注解只有在 public 方法上才会生效,同类中方法自调用会导致事务失效。
七、最佳实践
- 优先使用语义明确的注解 :使用
@Service、@Repository、@Controller代替通用的@Component - 优先使用构造方法注入:保证依赖不可变,便于单元测试,避免循环依赖
- 避免字段注入:字段注入虽然简洁,但有很多缺点,不推荐在生产环境中使用
- 合理使用 @Lazy:对于初始化耗时较长或很少使用的 Bean,可以使用延迟加载
- 统一使用派生注解 :使用
@GetMapping、@PostMapping等代替通用的@RequestMapping - @Transactional 正确使用 :标记在 public 方法上,指定
rollbackFor = Exception.class,避免同类自调用 - 批量配置使用 @ConfigurationProperties :当有多个相关配置时,使用
@ConfigurationProperties比@Value更方便
八、高频面试题解答
-
问:@Controller 和 @RestController 有什么区别? 答:
@RestController是组合注解,相当于@Controller + @ResponseBody。@Controller返回视图名称,用于服务端渲染;@RestController返回 JSON/XML 数据,用于前后端分离的 API 开发。 -
问:@Autowired 和 @Resource 有什么区别? 答:
@Autowired是 Spring 框架的注解,默认按类型注入;@Resource是 JSR-250 标准注解,默认按名称注入。@Autowired支持构造方法注入,@Resource不支持。 -
问:@Bean 和 @Component 有什么区别? 答:
@Component用于标记自己写的类,Spring 会自动扫描并注册为 Bean;@Bean用于在配置类中注册第三方库的类,或者需要复杂初始化逻辑的类。 -
问:@SpringBootApplication 包含哪些注解? 答:
@SpringBootApplication包含三个核心注解:@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。 -
问:@RequestParam 和 @PathVariable 有什么区别? 答:
@RequestParam用于获取 URL 查询参数(? 后面的参数),@PathVariable用于获取 URL 路径中的变量。 -
问:@Transactional 注解在什么情况下会失效? 答:常见的失效场景有:方法不是 public 的、同类中方法自调用、异常类型不是 RuntimeException、手动捕获异常没有抛出、错误的传播行为等。
九、总结
Spring 全家桶的注解是我们开发中最常用的工具,正确理解和使用这些注解是每个 Java 后端开发者的基本功。
回顾一下全文的核心内容:
- 核心组件注解:
@Component、@Service、@Repository、@Controller、@Configuration、@Bean - 依赖注入注解:
@Autowired、@Resource、@Qualifier、@Value - Spring MVC 注解:
@RestController、@GetMapping、@PostMapping、@RequestParam、@PathVariable、@RequestBody - Spring Boot 注解:
@SpringBootApplication、@ConfigurationProperties、@Conditional系列 - 事务注解:
@Transactional
掌握了这些常见注解,你就能轻松应对日常开发中的大部分场景,同时也能轻松通过相关的面试。记住:注解只是工具,理解它们的底层原理,才能写出更优雅、更健壮的代码。