news 2026/9/30 8:44:45

Spring 注解使用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring 注解使用详解

Spring 注解使用详解

Spring 的注解体系覆盖了从 Bean 注册、依赖注入、AOP、事务到 Web 开发的方方面面。注解把配置信息直接写在代码上,让开发和维护都更直观。本文按功能分类,逐一说明常用注解的用法、适用场景和底层机制。

一、注解生效的底层机制

Spring 处理注解主要依赖两个扩展点:

  • BeanPostProcessor:在 Bean 初始化前后介入,处理@Autowired、@Value、@PostConstruct等注解。AutowiredAnnotationBeanPostProcessor负责依赖注入,CommonAnnotationBeanPostProcessor负责@Resource、@PostConstruct、@PreDestroy。
  • BeanFactoryPostProcessor:在 Bean 实例化之前介入,处理@ComponentScan、@Configuration、@Bean等注解。ConfigurationClassPostProcessor负责解析配置类,生成 BeanDefinition。

注解本身不会“自动生效”,是这些后置处理器在容器启动时扫描并执行对应逻辑。

二、声明 Bean 的注解

1. @Component 及其派生注解

注解语义特殊功能
@Component通用组件无
@Service业务层无(语义清晰)
@Repository数据访问层异常转换
@ControllerWeb 控制层视图解析
@RestControllerREST 控制器直接返回 JSON
@Configuration配置类CGLIB 代理
@ServicepublicclassUserService{@AutowiredprivateUserDaouserDao;}@RepositorypublicclassUserDaoImplimplementsUserDao{@AutowiredprivateJdbcTemplatejdbcTemplate;}

Bean 名称默认是类名首字母小写,也可以显式指定:@Service("userService")。

2. @Bean

标注在@Configuration类的方法上,把返回值注册为 Bean。适合第三方类或需要复杂初始化逻辑的对象。

@ConfigurationpublicclassAppConfig{@BeanpublicDataSourcedataSource(){HikariDataSourceds=newHikariDataSource();ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");returnds;}@BeanpublicJdbcTemplatejdbcTemplate(DataSourcedataSource){returnnewJdbcTemplate(dataSource);}}

@Bean方法参数会自动从容器注入。@Bean(initMethod = "init", destroyMethod = "cleanup")可以指定初始化和销毁方法。

三、依赖注入注解

1. @Autowired

按类型自动注入,可以标注在字段、构造方法、Setter 方法上。

// 构造器注入(推荐)@ServicepublicclassUserService{privatefinalUserDaouserDao;publicUserService(UserDaouserDao){this.userDao=userDao;}}// 字段注入@ServicepublicclassUserService{@AutowiredprivateUserDaouserDao;}

required = false允许依赖为 null。构造器注入是 Spring 官方推荐的方式,保证依赖不可变且完全就绪。

2. @Qualifier

同类型有多个 Bean 时,按名称指定:

@ServicepublicclassOrderService{@Autowired@Qualifier("aliPayService")privatePaymentServicepaymentService;}

3. @Primary

同类型多 Bean 时,标记首选:

@Service@PrimarypublicclassAliPayServiceimplementsPaymentService{}

@Qualifier优先级高于@Primary。

4. @Value

注入简单类型和配置值:

@ComponentpublicclassAppConfig{@Value("${app.name}")privateStringappName;@Value("${app.timeout:30}")privateinttimeout;}

5. @Resource

JSR-250 标准,默认按名称注入:

@ServicepublicclassUserService{@Resource(name="userDaoImpl")privateUserDaouserDao;}

与@Autowired的区别:@Autowired默认按类型,@Resource默认按名称;@Autowired支持required = false和构造器注入,@Resource不支持。

四、配置与扫描注解

1. @ComponentScan

指定扫描包路径:

@Configuration@ComponentScan("com.example")publicclassAppConfig{}

2. @Import

导入其他配置类:

@Configuration@Import({DatabaseConfig.class,RedisConfig.class})publicclassAppConfig{}

3. @PropertySource

加载自定义 properties 文件:

@Configuration@PropertySource("classpath:custom.properties")publicclassAppConfig{@Value("${custom.value}")privateStringvalue;}

4. @ConfigurationProperties

批量绑定配置到对象:

@Component@ConfigurationProperties(prefix="app")@Getter@SetterpublicclassAppProperties{privateStringname;privateinttimeout;privateList<String>servers;}

五、条件化与 Profile 注解

1. @Conditional

根据条件决定是否注册 Bean:

@Bean@Conditional(WindowsCondition.class)publicFileServicewindowsFileService(){returnnewWindowsFileService();}

2. Spring Boot 条件注解

注解条件
@ConditionalOnClassclasspath 存在指定类
@ConditionalOnMissingBean容器中不存在指定 Bean
@ConditionalOnProperty配置属性满足条件
@ConditionalOnWebApplication是 Web 应用
@Bean@ConditionalOnMissingBeanpublicObjectMapperobjectMapper(){returnnewObjectMapper();}

3. @Profile

按环境激活:

@Configuration@Profile("dev")publicclassDevConfig{}@Configuration@Profile("prod")publicclassProdConfig{}

六、AOP 注解

1. 开启 AOP

@Configuration@EnableAspectJAutoProxypublicclassAopConfig{}

Spring Boot 中引入spring-boot-starter-aop后自动生效。

2. 定义切面

@Aspect@ComponentpublicclassLoggingAspect{@Pointcut("execution(* com.example.service.*.*(..))")publicvoidserviceLayer(){}@Before("serviceLayer()")publicvoidbefore(JoinPointjp){System.out.println("执行前:"+jp.getSignature().getName());}@AfterReturning(pointcut="serviceLayer()",returning="result")publicvoidafterReturning(JoinPointjp,Objectresult){System.out.println("返回:"+result);}@AfterThrowing(pointcut="serviceLayer()",throwing="ex")publicvoidafterThrowing(JoinPointjp,Exceptionex){System.out.println("异常:"+ex.getMessage());}@Around("serviceLayer()")publicObjectaround(ProceedingJoinPointpjp)throwsThrowable{longstart=System.currentTimeMillis();Objectresult=pjp.proceed();System.out.println("耗时:"+(System.currentTimeMillis()-start)+"ms");returnresult;}}

七、事务注解

@ServicepublicclassOrderService{@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED,timeout=30)publicvoidcreateOrder(Orderorder){orderDao.save(order);inventoryDao.decrease(order.getProductId(),order.getQuantity());}}

需要@EnableTransactionManagement(Spring Boot 自动配置)。注意@Transactional在同一个类内部调用不生效,必须通过代理调用。

八、Web 注解

1. 请求映射

@RestController@RequestMapping("/api/users")publicclassUserController{@GetMapping("/{id}")publicUsergetUser(@PathVariableLongid){returnuserService.getById(id);}@PostMappingpublicUsercreate(@RequestBody@ValidUseruser){returnuserService.save(user);}@GetMappingpublicList<User>list(@RequestParam(required=false)Stringname){returnuserService.findByName(name);}}

2. 全局异常处理

@RestControllerAdvicepublicclassGlobalExceptionHandler{@ExceptionHandler(BusinessException.class)publicResponseEntity<ErrorResponse>handleBusiness(BusinessExceptione){returnResponseEntity.badRequest().body(newErrorResponse(e.getMessage()));}}

九、测试注解

@SpringBootTestclassUserServiceTest{@AutowiredprivateUserServiceuserService;@MockBeanprivateUserDaouserDao;@TestvoidtestGetUser(){when(userDao.findById(1L)).thenReturn(newUser(1L,"张三"));Useruser=userService.getById(1L);assertEquals("张三",user.getName());}}

常用测试注解:@SpringBootTest、@WebMvcTest、@DataJpaTest、@MybatisTest、@MockBean、@SpyBean、@TestPropertySource。

十、其他常用注解

注解作用
@Async异步执行方法,需@EnableAsync
@Scheduled定时任务,需@EnableScheduling
@Cacheable缓存方法结果,需@EnableCaching
@CacheEvict清除缓存
@EventListener事件监听
@Order控制 Bean 加载顺序
@Lazy延迟初始化
@Scope指定作用域
@AsyncpublicCompletableFuture<String>sendEmail(Stringto){...}@Scheduled(cron="0 0 2 * * ?")publicvoiddailyReport(){...}@Cacheable(value="users",key="#id")publicUsergetUser(Longid){...}

十一、注解使用最佳实践

  • 按层选择语义注解:Controller 用@RestController,Service 用@Service,Dao 用@Repository。
  • 优先使用构造器注入,保证依赖不可变和完整。
  • 第三方类无法加注解时,用@Configuration+@Bean注册。
  • 多环境配置用@Profile,避免运行时 if-else。
  • 提供默认实现时用@ConditionalOnMissingBean,允许用户覆盖。
  • 事务注解放在 Service 层,注意内部调用失效问题。
  • AOP 切面只处理真正的横切关注点,避免滥用导致调试困难。
  • 测试中使用@MockBean隔离外部依赖,用切片测试代替完整@SpringBootTest提升速度。

十二、总结

分类核心注解
声明 Bean@Component、@Service、@Repository、@Controller、@RestController、@Configuration、@Bean
依赖注入@Autowired、@Qualifier、@Primary、@Value、@Resource
配置与扫描@ComponentScan、@Import、@PropertySource、@ConfigurationProperties
条件与 Profile@Conditional、@ConditionalOnXxx、@Profile
AOP@Aspect、@Pointcut、@Before、@After、@Around
事务@Transactional
Web@RequestMapping、@GetMapping、@PostMapping、@RequestParam、@PathVariable、@RequestBody、@RestControllerAdvice
测试@SpringBootTest、@MockBean、@WebMvcTest
其他@Async、@Scheduled、@Cacheable、@EventListener

Spring 注解体系庞大但逻辑清晰:声明 Bean 靠@Component系列和@Bean,注入依赖靠@Autowired系列,扩展功能靠@EnableXxx和条件注解。掌握这些注解的语义、生效机制和适用场景,就能在开发中灵活组合,写出简洁且易维护的 Spring 应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 8:44:04

Hindsight:基于日志回放的浏览器性能分析开源工具实战

第一次注意到“hindsight”这个词&#xff0c;是在翻Mozilla的GitHub仓库找性能分析工具的时候。说实话&#xff0c;当时扫到这个名字&#xff0c;第一反应是&#xff1a;这名字起得挺妙。Hindsight直译是“后见之明”&#xff0c;通俗点说就是“回头看清”&#xff0c;用来给一…

作者头像 李华
网站建设 2026/9/30 8:43:01

ITIL 4迁移的隐性陷阱:从价值流重构到考核换血的落地清单

坦白说&#xff0c;我见过太多团队把“ITIL 4迁移”做成了一场PPT改装秀。红头文件下发、全员轮训、流程文档重新排版、线上考试全员通过&#xff0c;结果半年后回头看&#xff0c;日常运维该找谁还是找谁&#xff0c;工单流转该卡还是卡&#xff0c;报销级别的变更审批依然在等…

作者头像 李华
网站建设 2026/9/30 8:42:46

AI Agent Skill安全攻防:OpenClaw生态的攻击面与防护

这两年AI Agent在国内外的普及速度&#xff0c;比大多数人预期的要快。OpenClaw、Claude Code、Cursor、Codex……每个生态都在把Skill做成核心扩展机制。Skill听着高大上&#xff0c;本质上就是一个可以塞给Agent的可执行技能包&#xff1a;一个说明文件加上若干脚本&#xff…

作者头像 李华
网站建设 2026/9/30 8:42:30

跨平台开发四大平台底层差异:指令集、ABI与工程实践

去年帮一个朋友查一个音视频处理工具的兼容性问题&#xff0c;他在 Intel Mac 上开发得顺风顺水&#xff0c;代码一放到 Apple Silicon 的机器上&#xff0c;编译倒是过了&#xff0c;但一运行就崩。折腾两天&#xff0c;最后定位到问题根源&#xff1a;代码里嵌了一段手写的 S…

作者头像 李华
网站建设 2026/9/30 8:42:15

故障复盘:P95延迟飙升背后的缓存击穿与连接池加固

大半夜被值班电话叫醒&#xff0c;屏幕上弹出一条告警&#xff1a;核心接口的P95延迟从80ms爬到了500ms。这原本是季度第七个运行维护专项启动后的第一周&#xff0c;我们要做的就是对核心交易链路的缓存和数据库层做一次全面加固&#xff0c;结果还没等我动手&#xff0c;故障…

作者头像 李华
网站建设 2026/9/30 8:42:07

一文读懂API接口CC攻击防护设计(实战笔记)

本文深入探讨API接口CC攻击防护设计&#xff08;实战笔记&#xff09;&#xff0c;涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。 作为DDoS与CC防护从业者&#xff0c;掌握API接口CC攻击防护设计&#xff08;实战笔记&#xff09;不仅能提升系统稳定性&am…

作者头像 李华