Spring 全家桶常见注解全解:从入门到精通

作为 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 指定哪些异常会导致事务回滚 RuntimeExceptionError
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 方法上才会生效,同类中方法自调用会导致事务失效。

七、最佳实践

  1. 优先使用语义明确的注解 :使用@Service@Repository@Controller代替通用的@Component
  2. 优先使用构造方法注入:保证依赖不可变,便于单元测试,避免循环依赖
  3. 避免字段注入:字段注入虽然简洁,但有很多缺点,不推荐在生产环境中使用
  4. 合理使用 @Lazy:对于初始化耗时较长或很少使用的 Bean,可以使用延迟加载
  5. 统一使用派生注解 :使用@GetMapping@PostMapping等代替通用的@RequestMapping
  6. @Transactional 正确使用 :标记在 public 方法上,指定rollbackFor = Exception.class,避免同类自调用
  7. 批量配置使用 @ConfigurationProperties :当有多个相关配置时,使用@ConfigurationProperties@Value更方便

八、高频面试题解答

  1. 问:@Controller 和 @RestController 有什么区别? 答:@RestController是组合注解,相当于@Controller + @ResponseBody@Controller返回视图名称,用于服务端渲染;@RestController返回 JSON/XML 数据,用于前后端分离的 API 开发。

  2. 问:@Autowired 和 @Resource 有什么区别? 答:@Autowired是 Spring 框架的注解,默认按类型注入;@Resource是 JSR-250 标准注解,默认按名称注入。@Autowired支持构造方法注入,@Resource不支持。

  3. 问:@Bean 和 @Component 有什么区别? 答:@Component用于标记自己写的类,Spring 会自动扫描并注册为 Bean;@Bean用于在配置类中注册第三方库的类,或者需要复杂初始化逻辑的类。

  4. 问:@SpringBootApplication 包含哪些注解? 答:@SpringBootApplication包含三个核心注解:@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan

  5. 问:@RequestParam 和 @PathVariable 有什么区别? 答:@RequestParam用于获取 URL 查询参数(? 后面的参数),@PathVariable用于获取 URL 路径中的变量。

  6. 问:@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

掌握了这些常见注解,你就能轻松应对日常开发中的大部分场景,同时也能轻松通过相关的面试。记住:注解只是工具,理解它们的底层原理,才能写出更优雅、更健壮的代码。

相关推荐
执笔论英雄10 小时前
GPU内存架构-DSMEM与L2
java·spring·架构
wb0430720110 小时前
从 Java 1 到 Java 26 的HTTP Client发展历程
java·开发语言·http
小则又沐风a11 小时前
进一步了解进程---第四章 进程管理
java·服务器·前端
超梦dasgg11 小时前
并查集(Union-Find)详解 + Java 完整实现
java·数据结构·算法·图搜索
WL_Aurora11 小时前
Java集合框架核心组件
java
我是一颗柠檬11 小时前
【JDK8新特性】Stream流API上Day4
java·开发语言·后端
超梦dasgg11 小时前
拆分大对象 + 流式处理 + 不一次性加载全量数据
java·jvm·windows
我是一颗柠檬11 小时前
【JDK8新特性】方法引用与构造器引用Day3
java·开发语言·后端·intellij-idea
在繁华处11 小时前
从零搭建轻灵(五):记忆系统与生产化特性
java·jvm·oracle