Spring Boot注解大赏:40个常用注解助你一臂之力

avatar
收快递IP属地:上海
02026-04-03:22:29:37字数 12186阅读 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属性显式指定扫描路径 。

(二)组件管理注解

  1. 通用组件@Component是一个通用的组件注解,它能够将普通的 Java 类标记为 Spring 可管理的 Bean 。当某个类难以归类到特定的分层中时,就可以使用@Component进行标注,例如工具类、自定义的拦截器等。

@Component
public class Utils {
    public void doSomething() {
        System.out.println("执行工具类方法");
    }
}
  1. 各层特化注解

    • @Controller:用于标记控制层组件,负责接收前端发送的 HTTP 请求,并将请求转发给相应的服务层进行处理,最终返回处理结果给前端。它是@Component的特化注解,在 Spring MVC 中扮演着关键角色 。

@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);
    }
}
  1. 配置类与 Bean 定义

    • @Configuration:用于标记配置类,它替代了传统的 XML 配置文件,在配置类中可以通过@Bean注解定义自定义的 Bean 。一个配置类就像是一个专门管理 Bean 的工厂,通过它可以灵活地配置和管理 Spring 容器中的 Bean。

@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,在其他组件中可以通过依赖注入的方式使用这个数据源。

(三)依赖注入注解

  1. @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);
    }
}
  1. @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);
    }
}

在上述例子中,假设存在userRepositoryMysqluserRepositoryOracle两个实现了UserRepository接口的 Bean,通过@Qualifier("userRepositoryMysql")就可以明确指定注入userRepositoryMysql这个 Bean 。

(四)Web 开发注解

  1. 请求映射

    • @RequestMapping:是 Spring MVC 中用于映射 HTTP 请求到控制器处理方法的注解,它可以标注在类和方法上 。在类上标注时,会为该类中的所有方法定义一个公共的请求路径前缀;在方法上标注时,则定义了该方法具体处理的请求路径和请求方法等信息。它拥有多个配置属性,如value用于指定请求路径,method用于指定请求方法(如RequestMethod.GETRequestMethod.POST等),params用于指定请求参数的条件等 。例如:

@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) {
        // 删除用户逻辑
    }
}
  1. 参数绑定

    • @PathVariable:用于从 URL 路径中提取参数,在 RESTful 风格的 API 中经常使用 。通过在方法参数前使用@PathVariable注解,并在请求路径中使用占位符(如{id}),可以将路径中的参数值绑定到方法参数上。例如:

@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) {
    // 根据分页参数获取用户列表逻辑
}
  1. 请求体与响应体

    • @RequestBody:用于将 HTTP 请求的主体内容转换为 Java 对象 。当前端发送 JSON、XML 等格式的数据时,通过在方法参数前使用@RequestBody注解,Spring 会自动将请求体中的数据转换为对应的 Java 对象,方便在后端进行处理。例如:

@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;
}
  1. RESTful 控制器与异常处理

    • @RestController:是@Controller@ResponseBody的组合注解,用于创建 RESTful 风格的控制器 。使用@RestController标记的类,其中的方法默认会将返回值转换为 JSON 或 XML 格式的数据返回给前端,而不是返回视图 。例如:

@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 "系统内部错误";
    }
}

(五)配置相关注解

  1. 属性注入@Value注解用于从配置文件中注入值到 Java 类的成员变量中,它支持注入常量值和读取配置文件中的配置项 。在配置文件(如application.propertiesapplication.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);
    }
}

(六)其他常用注解

  1. 事务管理@Transactional用于声明式事务管理,它可以标注在类或方法上 。当标注在类上时,该类中的所有公共方法都将加入事务管理;标注在方法上时,仅对该方法进行事务管理 。可以通过该注解指定事务的传播行为(如Propagation.REQUIREDPropagation.REQUIRES_NEW等)、隔离级别(如Isolation.DEFAULTIsolation.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);
    }
}

在上述例子中,如果reduceStocksave方法出现异常,整个事务会回滚,保证数据的一致性 。 2. 定时任务@Scheduled用于声明一个方法为定时任务,Spring 会按照指定的时间间隔或时间表达式来定时执行该方法 。可以通过cron属性指定 Cron 表达式来精确控制执行时间,也可以通过fixedRate属性指定固定的执行间隔时间(单位为毫秒) 。例如,每天凌晨 2 点执行数据备份任务:


@Component
public class BackupTask {
    @Scheduled(cron = "0 0 2 * *?")
    public void backupData() {
        // 数据备份逻辑
    }
}
  1. 数据校验@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 会自动处理并返回错误信息给前端 。

三、注解使用技巧与注意事项

(一)使用技巧

  1. 合理分层使用组件注解:在开发中,严格遵循 Controller - Service - Repository 的分层架构,正确使用@Controller@Service@Repository注解,能够使代码结构更加清晰,提高代码的可读性和可维护性 。比如,将所有与前端交互的逻辑放在@Controller层,将业务逻辑封装在@Service层,将数据访问逻辑放在@Repository层,这样各层职责明确,便于团队协作开发和后期维护 。

  2. 依赖注入的选择:对于必选依赖,建议使用构造函数注入,这样可以确保依赖在对象创建时就被正确注入,并且可以提高代码的可测试性 。例如:


@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // 业务方法
}

而对于可选依赖,可以使用字段注入或 Setter 方法注入 。 3. 灵活运用条件配置注解:在多环境开发中,@ConditionalOnProperty注解非常实用。可以通过配置文件来灵活控制不同环境下的配置和 Bean 的加载,避免在代码中硬编码环境相关的逻辑 。比如,在开发、测试、生产环境中,可能需要使用不同的数据库连接配置,通过@ConditionalOnProperty注解可以轻松实现根据spring.profiles.active属性的值来加载不同的数据源配置 。

(二)注意事项

  1. 循环依赖问题:在使用依赖注入注解(如@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;

    // 其他方法
}
  1. 配置错误:在使用注解进行配置时,如@Value注入属性值、@ConditionalOnProperty根据属性值加载 Bean 等,如果配置文件中的属性名错误、属性值格式不正确或者属性缺失,都可能导致程序运行时出现错误 。所以在配置时,一定要仔细检查属性名和属性值,并且可以为属性设置默认值,以防止属性缺失时引发异常 。

  2. 注解生效范围:要清楚各个注解的生效范围,比如@ComponentScan默认扫描启动类所在包及其子包,如果需要扫描其他包,需要显式指定扫描路径 。另外,@Configuration注解标记的配置类,如果不在扫描范围内,其中定义的 Bean 也不会被注册到 Spring 容器中 。

  3. 事务注解的使用限制@Transactional注解只能应用于公共方法,并且它基于 AOP 代理实现事务管理,所以在同一个类中方法之间的自调用,即使被调用方法添加了@Transactional注解,事务也不会生效 。如果需要在自调用中使用事务,可以通过注入自身代理或者使用 AspectJ 模式来解决 。

总资产 0
暂无其他文章

热门文章

暂无热门文章