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

张开发
2026/4/12 2:49:09 15 分钟阅读

分享文章

Spring Boot注解大赏:40个常用注解助你一臂之力
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 的配置类等同于ConfigurationEnableAutoConfiguration开启自动配置功能Spring Boot 会依据项目中引入的依赖自动配置相应的 Bean例如当项目中包含spring-boot-starter-web依赖时会自动配置 Tomcat 服务器和 Spring MVC 相关的 BeanComponentScan则用于组件扫描默认会扫描启动类所在包及其子包下被Component、Controller、Service、Repository等注解标记的类并将它们注册为 Spring 容器中的 Bean 。在使用时只需在 Spring Boot 应用的主类上添加SpringBootApplication注解即可启动整个应用。例如SpringBootApplicationpublicclassMySpringBootApp{publicstaticvoidmain(String[]args){SpringApplication.run(MySpringBootApp.class,args);}}常见错误若启动类所在包的位置不合理可能导致无法扫描到其他包下的组件从而引发组件未被注册到 Spring 容器中的错误。比如将启动类放置在一个较深的子包中而其他组件位于上级包或不同的同级包这时就需要通过scanBasePackages属性显式指定扫描路径 。二组件管理注解通用组件Component是一个通用的组件注解它能够将普通的 Java 类标记为 Spring 可管理的 Bean 。当某个类难以归类到特定的分层中时就可以使用Component进行标注例如工具类、自定义的拦截器等。ComponentpublicclassUtils{publicvoiddoSomething(){System.out.println(执行工具类方法);}}各层特化注解Controller用于标记控制层组件负责接收前端发送的 HTTP 请求并将请求转发给相应的服务层进行处理最终返回处理结果给前端。它是Component的特化注解在 Spring MVC 中扮演着关键角色 。ControllerRequestMapping(/user)publicclassUserController{AutowiredprivateUserServiceuserService;GetMapping(/get)ResponseBodypublicUsergetUser(Longid){returnuserService.getUserById(id);}}Service主要用于标记服务层组件负责处理具体的业务逻辑。它同样是Component的特化注解通过将业务逻辑封装在服务层可以使代码结构更加清晰便于维护和扩展 。ServicepublicclassUserService{AutowiredprivateUserRepositoryuserRepository;publicUsergetUserById(Longid){returnuserRepository.findById(id).orElse(null);}}Repository专门用于标记数据访问层组件通常与数据库进行交互执行数据的增删改查操作。它也是Component的特化注解并且 Spring 会自动为其提供异常转换功能将底层的数据访问异常如 JDBC 的SQLException转换为 Spring 统一的DataAccessException体系方便上层进行统一的异常处理 。RepositorypublicclassUserRepository{AutowiredprivateJdbcTemplatejdbcTemplate;publicUserfindById(Longid){StringsqlSELECT * FROM user WHERE id ?;returnjdbcTemplate.queryForObject(sql,newBeanPropertyRowMapper(User.class),id);}}配置类与 Bean 定义Configuration用于标记配置类它替代了传统的 XML 配置文件在配置类中可以通过Bean注解定义自定义的 Bean 。一个配置类就像是一个专门管理 Bean 的工厂通过它可以灵活地配置和管理 Spring 容器中的 Bean。ConfigurationpublicclassAppConfig{BeanpublicDataSourcedataSource(){// 配置数据源returnnewDriverManagerDataSource(jdbc:mysql://localhost:3306/mydb,root,password);}}Bean通常用于在配置类中定义 Bean它标记的方法返回值将作为一个 Bean 注册到 Spring 容器中Bean 的名称默认为方法名 。在上面的AppConfig配置类中dataSource方法返回的DataSource实例就会被注册为一个 Bean在其他组件中可以通过依赖注入的方式使用这个数据源。三依赖注入注解AutowiredAutowired是 Spring 框架提供的依赖注入注解它能够按照类型自动将依赖对象注入到目标组件中。可以将其标注在构造方法、字段、Setter 方法等位置 。在实际应用中经常会在 Controller 中注入 Service在 Service 中注入 Repository。例如ServicepublicclassOrderService{AutowiredprivateOrderRepositoryorderRepository;publicvoidsaveOrder(Orderorder){orderRepository.save(order);}}使用Autowired进行依赖注入不仅可以避免手动创建对象的繁琐过程还能有效降低代码的耦合度使得代码更加简洁和易于维护。同时它还能很好地解决循环依赖的问题并且在进行单元测试时便于对依赖进行模拟和替换 。2.ResourceResource是 JDK 自带的注解属于 Java EE 标准它也用于依赖注入 。与Autowired不同的是Resource默认按名称进行注入如果未指定名称则按类型匹配。在 Spring Boot 中它通过CommonAnnotationBeanPostProcessor类实现自动装配。例如ControllerpublicclassUserController{Resource(nameuserService)privateUserServiceuserService;GetMapping(/getUser)ResponseBodypublicUsergetUser(Longid){returnuserService.getUserById(id);}}Qualifier当同一类型的 Bean 在 Spring 容器中有多个时使用Autowired会出现歧义无法确定具体要注入哪个 Bean 。此时就可以使用Qualifier注解与Autowired配合使用通过指定 Bean 的名称来实现精准匹配。例如ServicepublicclassUserService{AutowiredQualifier(userRepositoryMysql)privateUserRepositoryuserRepository;publicvoidsaveUser(Useruser){userRepository.save(user);}}在上述例子中假设存在userRepositoryMysql和userRepositoryOracle两个实现了UserRepository接口的 Bean通过Qualifier(userRepositoryMysql)就可以明确指定注入userRepositoryMysql这个 Bean 。四Web 开发注解请求映射RequestMapping是 Spring MVC 中用于映射 HTTP 请求到控制器处理方法的注解它可以标注在类和方法上 。在类上标注时会为该类中的所有方法定义一个公共的请求路径前缀在方法上标注时则定义了该方法具体处理的请求路径和请求方法等信息。它拥有多个配置属性如value用于指定请求路径method用于指定请求方法如RequestMethod.GET、RequestMethod.POST等params用于指定请求参数的条件等 。例如ControllerRequestMapping(/product)publicclassProductController{RequestMapping(value/get,methodRequestMethod.GET)ResponseBodypublicProductgetProduct(Longid){// 获取产品逻辑}}GetMapping、PostMapping、PutMapping、DeleteMapping这些注解是RequestMapping的简化版它们分别对应 HTTP 的 GET、POST、PUT、DELETE 请求方法 。使用这些注解可以使代码更加简洁明了语义更加清晰在 RESTful 风格的接口开发中被广泛使用 。例如RestControllerRequestMapping(/user)publicclassUserController{GetMapping(/getById/{id})publicUsergetUserById(PathVariableLongid){// 根据ID获取用户逻辑}PostMapping(/add)publicStringaddUser(RequestBodyUseruser){// 添加用户逻辑}PutMapping(/update)publicStringupdateUser(RequestBodyUseruser){// 更新用户逻辑}DeleteMapping(/delete/{id})publicStringdeleteUser(PathVariableLongid){// 删除用户逻辑}}参数绑定PathVariable用于从 URL 路径中提取参数在 RESTful 风格的 API 中经常使用 。通过在方法参数前使用PathVariable注解并在请求路径中使用占位符如{id}可以将路径中的参数值绑定到方法参数上。例如GetMapping(/user/{id})ResponseBodypublicUsergetUserById(PathVariableLongid){// 根据ID获取用户逻辑}RequestParam用于绑定请求参数它可以从 URL 的查询参数中获取值并将其绑定到方法参数上 。可以指定参数名、是否必传、默认值等属性。例如GetMapping(/user/list)ResponseBodypublicListUsergetUserList(RequestParam(namepage,defaultValue1)intpage,RequestParam(namesize,defaultValue10)intsize){// 根据分页参数获取用户列表逻辑}请求体与响应体RequestBody用于将 HTTP 请求的主体内容转换为 Java 对象 。当前端发送 JSON、XML 等格式的数据时通过在方法参数前使用RequestBody注解Spring 会自动将请求体中的数据转换为对应的 Java 对象方便在后端进行处理。例如PostMapping(/user/add)ResponseBodypublicStringaddUser(RequestBodyUseruser){// 添加用户逻辑}ResponseBody用于将方法的返回值写入 HTTP 响应体中 。它会将返回值转换为 JSON、XML 等格式的数据返回给前端。在RestController中已经包含了ResponseBody的功能所以RestController标记的控制器方法返回值会自动转换为响应体数据返回 。例如GetMapping(/user/get)ResponseBodypublicUsergetUser(Longid){// 获取用户逻辑returnuser;}RESTful 控制器与异常处理RestController是Controller和ResponseBody的组合注解用于创建 RESTful 风格的控制器 。使用RestController标记的类其中的方法默认会将返回值转换为 JSON 或 XML 格式的数据返回给前端而不是返回视图 。例如RestControllerRequestMapping(/api)publicclassApiController{GetMapping(/data)publicDatagetData(){// 获取数据逻辑returndata;}}ControllerAdvice结合ExceptionHandler、InitBinder、ModelAttribute等注解用于处理全局异常、统一数据绑定、统一模型数据等 。通过ControllerAdvice可以将这些通用的处理逻辑集中在一个类中避免在每个控制器中重复编写。例如统一处理异常的示例ControllerAdvicepublicclassGlobalExceptionHandler{ExceptionHandler(Exception.class)ResponseBodypublicStringhandleException(Exceptione){// 记录异常日志e.printStackTrace();return系统内部错误;}}五配置相关注解属性注入Value注解用于从配置文件中注入值到 Java 类的成员变量中它支持注入常量值和读取配置文件中的配置项 。在配置文件如application.properties或application.yml中定义配置项后在 Java 类中使用Value注解即可获取对应的值。例如在application.properties中定义app.secretKey123456在 Java 类中使用ComponentpublicclassConfig{Value(${app.secretKey})privateStringsecretKey;publicvoidprintSecretKey(){System.out.println(密钥secretKey);}}常见错误如果配置文件中不存在对应的配置项并且没有设置默认值会抛出IllegalArgumentException: Could not resolve placeholder异常 。所以在使用时最好为配置项设置默认值如Value(${app.secretKey:defaultValue})。2.条件配置ConditionalOnProperty根据配置文件中的属性值来动态决定是否加载某个 Bean 。它可以指定属性名、属性值、是否必须存在等条件。例如在开发多环境配置时根据spring.profiles.active属性的值来加载不同的数据源配置 。ConfigurationpublicclassDataSourceConfig{BeanConditionalOnProperty(namespring.profiles.active,havingValuedev)publicDataSourcedevDataSource(){// 开发环境数据源配置}BeanConditionalOnProperty(namespring.profiles.active,havingValueprod)publicDataSourceprodDataSource(){// 生产环境数据源配置}}ConditionalOnClass根据类路径中是否存在指定的类来决定某个配置或 Bean 是否生效 。在自动配置中经常使用例如当项目中引入了spring-boot-starter-jdbc依赖就会自动配置JdbcTemplate相关的 Bean这可以通过ConditionalOnClass(JdbcTemplate.class)来实现 。ConfigurationConditionalOnClass(JdbcTemplate.class)publicclassJdbcConfig{BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){returnnewJdbcTemplate(dataSource);}}六其他常用注解事务管理Transactional用于声明式事务管理它可以标注在类或方法上 。当标注在类上时该类中的所有公共方法都将加入事务管理标注在方法上时仅对该方法进行事务管理 。可以通过该注解指定事务的传播行为如Propagation.REQUIRED、Propagation.REQUIRES_NEW等、隔离级别如Isolation.DEFAULT、Isolation.READ_COMMITTED等、回滚规则等 。例如在业务层中进行数据库操作时保证多个操作要么全部成功要么全部失败ServicepublicclassOrderService{AutowiredprivateOrderRepositoryorderRepository;AutowiredprivateProductRepositoryproductRepository;Transactional(rollbackForException.class)publicvoidplaceOrder(Orderorder){// 扣除商品库存productRepository.reduceStock(order.getProductId(),order.getQuantity());// 保存订单orderRepository.save(order);}}在上述例子中如果reduceStock或save方法出现异常整个事务会回滚保证数据的一致性 。2.定时任务Scheduled用于声明一个方法为定时任务Spring 会按照指定的时间间隔或时间表达式来定时执行该方法 。可以通过cron属性指定 Cron 表达式来精确控制执行时间也可以通过fixedRate属性指定固定的执行间隔时间单位为毫秒 。例如每天凌晨 2 点执行数据备份任务ComponentpublicclassBackupTask{Scheduled(cron0 0 2 * *?)publicvoidbackupData(){// 数据备份逻辑}}数据校验Valid用于结合 JSR - 303 规范进行数据校验它可以对请求体中的参数进行校验确保数据的合法性 。在 Controller 中使用Valid注解配合校验注解如NotNull、Size、Email等可以在参数进入方法前进行校验 。例如RestControllerRequestMapping(/user)publicclassUserController{PostMapping(/add)publicStringaddUser(ValidRequestBodyUseruser){// 添加用户逻辑}}在上述例子中User类中的属性如果添加了校验注解如NotNull当前端发送的请求体中User对象的该属性为空时会抛出校验异常Spring 会自动处理并返回错误信息给前端 。三、注解使用技巧与注意事项一使用技巧合理分层使用组件注解在开发中严格遵循 Controller - Service - Repository 的分层架构正确使用Controller、Service、Repository注解能够使代码结构更加清晰提高代码的可读性和可维护性 。比如将所有与前端交互的逻辑放在Controller层将业务逻辑封装在Service层将数据访问逻辑放在Repository层这样各层职责明确便于团队协作开发和后期维护 。依赖注入的选择对于必选依赖建议使用构造函数注入这样可以确保依赖在对象创建时就被正确注入并且可以提高代码的可测试性 。例如ServicepublicclassUserService{privatefinalUserRepositoryuserRepository;publicUserService(UserRepositoryuserRepository){this.userRepositoryuserRepository;}// 业务方法}而对于可选依赖可以使用字段注入或 Setter 方法注入 。3.灵活运用条件配置注解在多环境开发中ConditionalOnProperty注解非常实用。可以通过配置文件来灵活控制不同环境下的配置和 Bean 的加载避免在代码中硬编码环境相关的逻辑 。比如在开发、测试、生产环境中可能需要使用不同的数据库连接配置通过ConditionalOnProperty注解可以轻松实现根据spring.profiles.active属性的值来加载不同的数据源配置 。二注意事项循环依赖问题在使用依赖注入注解如Autowired时可能会出现循环依赖的问题即 A 类依赖 B 类B 类又依赖 A 类 。Spring Boot 通过提前暴露创建中的 Bean 来解决大部分循环依赖问题但对于构造函数注入的循环依赖仍然会抛出BeanCurrentlyInCreationException异常 。解决方法可以采用 Setter 方法注入或使用Lazy注解延迟加载依赖 。例如ServicepublicclassA{AutowiredLazyprivateBb;// 其他方法}ServicepublicclassB{AutowiredprivateAa;// 其他方法}配置错误在使用注解进行配置时如Value注入属性值、ConditionalOnProperty根据属性值加载 Bean 等如果配置文件中的属性名错误、属性值格式不正确或者属性缺失都可能导致程序运行时出现错误 。所以在配置时一定要仔细检查属性名和属性值并且可以为属性设置默认值以防止属性缺失时引发异常 。注解生效范围要清楚各个注解的生效范围比如ComponentScan默认扫描启动类所在包及其子包如果需要扫描其他包需要显式指定扫描路径 。另外Configuration注解标记的配置类如果不在扫描范围内其中定义的 Bean 也不会被注册到 Spring 容器中 。事务注解的使用限制Transactional注解只能应用于公共方法并且它基于 AOP 代理实现事务管理所以在同一个类中方法之间的自调用即使被调用方法添加了Transactional注解事务也不会生效 。如果需要在自调用中使用事务可以通过注入自身代理或者使用 AspectJ 模式来解决 。

更多文章