0赞
赞赏
更多好文
Spring Boot注解大赏:40个常用注解助你一臂之力
一、Spring Boot 注解的奇妙世界
在 Java 开发的广袤天地中,Spring Boot 就像是一把神奇的瑞士军刀,已然成为众多开发者构建项目的首选框架。它以其 “约定优于配置” 的理念,极大地简化了开发流程,让开发者们从繁琐的配置文件中解脱出来,专注于业务逻辑的实现。无论是小型项目的快速搭建,还是大型企业级应用的架构设计,Spring Boot 都能轻松胜任,在企业级应用开发中占据着举足轻重的地位 。
而在 Spring Boot 的开发过程中,注解就像是隐藏在幕后的魔法精灵,发挥着不可或缺的关键作用。它们以简洁的语法,为代码赋予了丰富的元数据信息,从而实现了各种强大的功能。从组件的自动扫描与注册,到依赖的自动注入,再到请求的映射与处理,甚至是事务的管理和配置的读取,注解都无处不在,成为了 Spring Boot 开发中不可或缺的一部分。可以毫不夸张地说,掌握了 Spring Boot 的常用注解,就如同掌握了开启 Spring Boot 强大功能之门的钥匙,能够让你的开发效率得到质的飞跃。接下来,就让我们一起深入探索这 40 个 Spring Boot 常用注解的奇妙世界吧!
二、40 个常用注解大盘点
(一)核心启动注解
- @SpringBootApplication:这是 Spring Boot 应用中最为核心的启动注解,它实际上是一个组合注解,整合了
@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan这三个关键注解的功能 。其中,@SpringBootConfiguration表明该类是 Spring Boot 的配置类,等同于@Configuration;@EnableAutoConfiguration开启自动配置功能,Spring Boot 会依据项目中引入的依赖,自动配置相应的 Bean,例如,当项目中包含spring-boot-starter-web依赖时,会自动配置 Tomcat 服务器和 Spring MVC 相关的 Bean;@ComponentScan则用于组件扫描,默认会扫描启动类所在包及其子包下被@Component、@Controller、@Service、@Repository等注解标记的类,并将它们注册为 Spring 容器中的 Bean 。
在使用时,只需在 Spring Boot 应用的主类上添加@SpringBootApplication注解,即可启动整个应用。例如:
@SpringBootApplication
public class MySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApp.class, args);
}
}
常见错误:若启动类所在包的位置不合理,可能导致无法扫描到其他包下的组件,从而引发组件未被注册到 Spring 容器中的错误。比如,将启动类放置在一个较深的子包中,而其他组件位于上级包或不同的同级包,这时就需要通过scanBasePackages属性显式指定扫描路径 。
(二)组件管理注解
- 通用组件:
@Component是一个通用的组件注解,它能够将普通的 Java 类标记为 Spring 可管理的 Bean 。当某个类难以归类到特定的分层中时,就可以使用@Component进行标注,例如工具类、自定义的拦截器等。
@Component
public class Utils {
public void doSomething() {
System.out.println("执行工具类方法");
}
}
-
各层特化注解:
- @Controller:用于标记控制层组件,负责接收前端发送的 HTTP 请求,并将请求转发给相应的服务层进行处理,最终返回处理结果给前端。它是
@Component的特化注解,在 Spring MVC 中扮演着关键角色 。
- @Controller:用于标记控制层组件,负责接收前端发送的 HTTP 请求,并将请求转发给相应的服务层进行处理,最终返回处理结果给前端。它是
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/get")
@ResponseBody
public User getUser(Long id) {
return userService.getUserById(id);
}
}
- @Service:主要用于标记服务层组件,负责处理具体的业务逻辑。它同样是
@Component的特化注解,通过将业务逻辑封装在服务层,可以使代码结构更加清晰,便于维护和扩展 。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
}
- @Repository:专门用于标记数据访问层组件,通常与数据库进行交互,执行数据的增删改查操作。它也是
@Component的特化注解,并且 Spring 会自动为其提供异常转换功能,将底层的数据访问异常(如 JDBC 的SQLException)转换为 Spring 统一的DataAccessException体系,方便上层进行统一的异常处理 。
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
String sql = "SELECT * FROM user WHERE id =?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
}
}
-
配置类与 Bean 定义:
- @Configuration:用于标记配置类,它替代了传统的 XML 配置文件,在配置类中可以通过
@Bean注解定义自定义的 Bean 。一个配置类就像是一个专门管理 Bean 的工厂,通过它可以灵活地配置和管理 Spring 容器中的 Bean。
- @Configuration:用于标记配置类,它替代了传统的 XML 配置文件,在配置类中可以通过
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
// 配置数据源
return new DriverManagerDataSource("jdbc:mysql://localhost:3306/mydb", "root", "password");
}
}
- @Bean:通常用于在配置类中定义 Bean,它标记的方法返回值将作为一个 Bean 注册到 Spring 容器中,Bean 的名称默认为方法名 。在上面的
AppConfig配置类中,dataSource方法返回的DataSource实例就会被注册为一个 Bean,在其他组件中可以通过依赖注入的方式使用这个数据源。
(三)依赖注入注解
- @Autowired:
@Autowired是 Spring 框架提供的依赖注入注解,它能够按照类型自动将依赖对象注入到目标组件中。可以将其标注在构造方法、字段、Setter 方法等位置 。在实际应用中,经常会在 Controller 中注入 Service,在 Service 中注入 Repository。例如:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
public void saveOrder(Order order) {
orderRepository.save(order);
}
}
使用@Autowired进行依赖注入,不仅可以避免手动创建对象的繁琐过程,还能有效降低代码的耦合度,使得代码更加简洁和易于维护。同时,它还能很好地解决循环依赖的问题,并且在进行单元测试时,便于对依赖进行模拟和替换 。
2. @Resource:@Resource是 JDK 自带的注解,属于 Java EE 标准,它也用于依赖注入 。与@Autowired不同的是,@Resource默认按名称进行注入,如果未指定名称,则按类型匹配。在 Spring Boot 中,它通过CommonAnnotationBeanPostProcessor类实现自动装配。例如:
@Controller
public class UserController {
@Resource(name = "userService")
private UserService userService;
@GetMapping("/getUser")
@ResponseBody
public User getUser(Long id) {
return userService.getUserById(id);
}
}
- @Qualifier:当同一类型的 Bean 在 Spring 容器中有多个时,使用
@Autowired会出现歧义,无法确定具体要注入哪个 Bean 。此时,就可以使用@Qualifier注解与@Autowired配合使用,通过指定 Bean 的名称来实现精准匹配。例如:
@Service
public class UserService {
@Autowired
@Qualifier("userRepositoryMysql")
private UserRepository userRepository;
public void saveUser(User user) {
userRepository.save(user);
}
}
在上述例子中,假设存在userRepositoryMysql和userRepositoryOracle两个实现了UserRepository接口的 Bean,通过@Qualifier("userRepositoryMysql")就可以明确指定注入userRepositoryMysql这个 Bean 。
(四)Web 开发注解
-
请求映射:
- @RequestMapping:是 Spring MVC 中用于映射 HTTP 请求到控制器处理方法的注解,它可以标注在类和方法上 。在类上标注时,会为该类中的所有方法定义一个公共的请求路径前缀;在方法上标注时,则定义了该方法具体处理的请求路径和请求方法等信息。它拥有多个配置属性,如
value用于指定请求路径,method用于指定请求方法(如RequestMethod.GET、RequestMethod.POST等),params用于指定请求参数的条件等 。例如:
- @RequestMapping:是 Spring MVC 中用于映射 HTTP 请求到控制器处理方法的注解,它可以标注在类和方法上 。在类上标注时,会为该类中的所有方法定义一个公共的请求路径前缀;在方法上标注时,则定义了该方法具体处理的请求路径和请求方法等信息。它拥有多个配置属性,如
@Controller
@RequestMapping("/product")
public class ProductController {
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public Product getProduct(Long id) {
// 获取产品逻辑
}
}
- @GetMapping、@PostMapping、@PutMapping、@DeleteMapping:这些注解是
@RequestMapping的简化版,它们分别对应 HTTP 的 GET、POST、PUT、DELETE 请求方法 。使用这些注解可以使代码更加简洁明了,语义更加清晰,在 RESTful 风格的接口开发中被广泛使用 。例如:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/getById/{id}")
public User getUserById(@PathVariable Long id) {
// 根据ID获取用户逻辑
}
@PostMapping("/add")
public String addUser(@RequestBody User user) {
// 添加用户逻辑
}
@PutMapping("/update")
public String updateUser(@RequestBody User user) {
// 更新用户逻辑
}
@DeleteMapping("/delete/{id}")
public String deleteUser(@PathVariable Long id) {
// 删除用户逻辑
}
}
-
参数绑定:
- @PathVariable:用于从 URL 路径中提取参数,在 RESTful 风格的 API 中经常使用 。通过在方法参数前使用
@PathVariable注解,并在请求路径中使用占位符(如{id}),可以将路径中的参数值绑定到方法参数上。例如:
- @PathVariable:用于从 URL 路径中提取参数,在 RESTful 风格的 API 中经常使用 。通过在方法参数前使用
@GetMapping("/user/{id}")
@ResponseBody
public User getUserById(@PathVariable Long id) {
// 根据ID获取用户逻辑
}
- @RequestParam:用于绑定请求参数,它可以从 URL 的查询参数中获取值,并将其绑定到方法参数上 。可以指定参数名、是否必传、默认值等属性。例如:
@GetMapping("/user/list")
@ResponseBody
public List<User> getUserList(@RequestParam(name = "page", defaultValue = "1") int page,
@RequestParam(name = "size", defaultValue = "10") int size) {
// 根据分页参数获取用户列表逻辑
}
-
请求体与响应体:
- @RequestBody:用于将 HTTP 请求的主体内容转换为 Java 对象 。当前端发送 JSON、XML 等格式的数据时,通过在方法参数前使用
@RequestBody注解,Spring 会自动将请求体中的数据转换为对应的 Java 对象,方便在后端进行处理。例如:
- @RequestBody:用于将 HTTP 请求的主体内容转换为 Java 对象 。当前端发送 JSON、XML 等格式的数据时,通过在方法参数前使用
@PostMapping("/user/add")
@ResponseBody
public String addUser(@RequestBody User user) {
// 添加用户逻辑
}
- @ResponseBody:用于将方法的返回值写入 HTTP 响应体中 。它会将返回值转换为 JSON、XML 等格式的数据返回给前端。在
@RestController中,已经包含了@ResponseBody的功能,所以@RestController标记的控制器方法返回值会自动转换为响应体数据返回 。例如:
@GetMapping("/user/get")
@ResponseBody
public User getUser(Long id) {
// 获取用户逻辑
return user;
}
-
RESTful 控制器与异常处理:
- @RestController:是
@Controller和@ResponseBody的组合注解,用于创建 RESTful 风格的控制器 。使用@RestController标记的类,其中的方法默认会将返回值转换为 JSON 或 XML 格式的数据返回给前端,而不是返回视图 。例如:
- @RestController:是
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/data")
public Data getData() {
// 获取数据逻辑
return data;
}
}
- @ControllerAdvice:结合
@ExceptionHandler、@InitBinder、@ModelAttribute等注解,用于处理全局异常、统一数据绑定、统一模型数据等 。通过@ControllerAdvice可以将这些通用的处理逻辑集中在一个类中,避免在每个控制器中重复编写。例如,统一处理异常的示例:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleException(Exception e) {
// 记录异常日志
e.printStackTrace();
return "系统内部错误";
}
}
(五)配置相关注解
- 属性注入:
@Value注解用于从配置文件中注入值到 Java 类的成员变量中,它支持注入常量值和读取配置文件中的配置项 。在配置文件(如application.properties或application.yml)中定义配置项后,在 Java 类中使用@Value注解即可获取对应的值。例如,在application.properties中定义:
app.secretKey=123456
在 Java 类中使用:
@Component
public class Config {
@Value("${app.secretKey}")
private String secretKey;
public void printSecretKey() {
System.out.println("密钥:" + secretKey);
}
}
常见错误:如果配置文件中不存在对应的配置项,并且没有设置默认值,会抛出IllegalArgumentException: Could not resolve placeholder异常 。所以在使用时,最好为配置项设置默认值,如@Value("${app.secretKey:defaultValue}")。
2. 条件配置:
- @ConditionalOnProperty:根据配置文件中的属性值来动态决定是否加载某个 Bean 。它可以指定属性名、属性值、是否必须存在等条件。例如,在开发多环境配置时,根据
spring.profiles.active属性的值来加载不同的数据源配置 。
@Configuration
public class DataSourceConfig {
@Bean
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev")
public DataSource devDataSource() {
// 开发环境数据源配置
}
@Bean
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "prod")
public DataSource prodDataSource() {
// 生产环境数据源配置
}
}
- @ConditionalOnClass:根据类路径中是否存在指定的类来决定某个配置或 Bean 是否生效 。在自动配置中经常使用,例如,当项目中引入了
spring-boot-starter-jdbc依赖,就会自动配置JdbcTemplate相关的 Bean,这可以通过@ConditionalOnClass(JdbcTemplate.class)来实现 。
@Configuration
@ConditionalOnClass(JdbcTemplate.class)
public class JdbcConfig {
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
(六)其他常用注解
- 事务管理:
@Transactional用于声明式事务管理,它可以标注在类或方法上 。当标注在类上时,该类中的所有公共方法都将加入事务管理;标注在方法上时,仅对该方法进行事务管理 。可以通过该注解指定事务的传播行为(如Propagation.REQUIRED、Propagation.REQUIRES_NEW等)、隔离级别(如Isolation.DEFAULT、Isolation.READ_COMMITTED等)、回滚规则等 。例如,在业务层中进行数据库操作时,保证多个操作要么全部成功,要么全部失败:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private ProductRepository productRepository;
@Transactional(rollbackFor = Exception.class)
public void placeOrder(Order order) {
// 扣除商品库存
productRepository.reduceStock(order.getProductId(), order.getQuantity());
// 保存订单
orderRepository.save(order);
}
}
在上述例子中,如果reduceStock或save方法出现异常,整个事务会回滚,保证数据的一致性 。
2. 定时任务:@Scheduled用于声明一个方法为定时任务,Spring 会按照指定的时间间隔或时间表达式来定时执行该方法 。可以通过cron属性指定 Cron 表达式来精确控制执行时间,也可以通过fixedRate属性指定固定的执行间隔时间(单位为毫秒) 。例如,每天凌晨 2 点执行数据备份任务:
@Component
public class BackupTask {
@Scheduled(cron = "0 0 2 * *?")
public void backupData() {
// 数据备份逻辑
}
}
- 数据校验:
@Valid用于结合 JSR - 303 规范进行数据校验,它可以对请求体中的参数进行校验,确保数据的合法性 。在 Controller 中使用@Valid注解,配合校验注解(如@NotNull、@Size、@Email等),可以在参数进入方法前进行校验 。例如:
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/add")
public String addUser(@Valid @RequestBody User user) {
// 添加用户逻辑
}
}
在上述例子中,User类中的属性如果添加了校验注解,如@NotNull,当前端发送的请求体中User对象的该属性为空时,会抛出校验异常,Spring 会自动处理并返回错误信息给前端 。
三、注解使用技巧与注意事项
(一)使用技巧
-
合理分层使用组件注解:在开发中,严格遵循 Controller - Service - Repository 的分层架构,正确使用
@Controller、@Service、@Repository注解,能够使代码结构更加清晰,提高代码的可读性和可维护性 。比如,将所有与前端交互的逻辑放在@Controller层,将业务逻辑封装在@Service层,将数据访问逻辑放在@Repository层,这样各层职责明确,便于团队协作开发和后期维护 。 -
依赖注入的选择:对于必选依赖,建议使用构造函数注入,这样可以确保依赖在对象创建时就被正确注入,并且可以提高代码的可测试性 。例如:
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 业务方法
}
而对于可选依赖,可以使用字段注入或 Setter 方法注入 。
3. 灵活运用条件配置注解:在多环境开发中,@ConditionalOnProperty注解非常实用。可以通过配置文件来灵活控制不同环境下的配置和 Bean 的加载,避免在代码中硬编码环境相关的逻辑 。比如,在开发、测试、生产环境中,可能需要使用不同的数据库连接配置,通过@ConditionalOnProperty注解可以轻松实现根据spring.profiles.active属性的值来加载不同的数据源配置 。
(二)注意事项
- 循环依赖问题:在使用依赖注入注解(如
@Autowired)时,可能会出现循环依赖的问题,即 A 类依赖 B 类,B 类又依赖 A 类 。Spring Boot 通过提前暴露创建中的 Bean 来解决大部分循环依赖问题,但对于构造函数注入的循环依赖,仍然会抛出BeanCurrentlyInCreationException异常 。解决方法可以采用 Setter 方法注入或使用@Lazy注解延迟加载依赖 。例如:
@Service
public class A {
@Autowired
@Lazy
private B b;
// 其他方法
}
@Service
public class B {
@Autowired
private A a;
// 其他方法
}
-
配置错误:在使用注解进行配置时,如
@Value注入属性值、@ConditionalOnProperty根据属性值加载 Bean 等,如果配置文件中的属性名错误、属性值格式不正确或者属性缺失,都可能导致程序运行时出现错误 。所以在配置时,一定要仔细检查属性名和属性值,并且可以为属性设置默认值,以防止属性缺失时引发异常 。 -
注解生效范围:要清楚各个注解的生效范围,比如
@ComponentScan默认扫描启动类所在包及其子包,如果需要扫描其他包,需要显式指定扫描路径 。另外,@Configuration注解标记的配置类,如果不在扫描范围内,其中定义的 Bean 也不会被注册到 Spring 容器中 。 -
事务注解的使用限制:
@Transactional注解只能应用于公共方法,并且它基于 AOP 代理实现事务管理,所以在同一个类中方法之间的自调用,即使被调用方法添加了@Transactional注解,事务也不会生效 。如果需要在自调用中使用事务,可以通过注入自身代理或者使用 AspectJ 模式来解决 。
