Spring Spring Boot 常用注解详解:生命周期、懒加载、优先加载与实用技巧
Spring & Spring Boot 常用注解详解:生命周期、懒加载、优先加载与实用技巧
前言
在 Spring 和 Spring Boot 开发中,注解几乎是“每天必打交道”的伙伴。它们像魔法一样,可以帮你声明 Bean、管理依赖、控制加载顺序、处理事务、配置环境……但注解多了也容易混淆。本教程将按功能模块,带你系统梳理 Spring 生态中最常用的注解,尤其会重点讲解生命周期、懒加载和优先加载相关的那些“容易踩坑”的注解。全文配合示例,希望对你的日常开发有所助益。
目录
- 核心组件注解——声明一个 Bean
- 配置与注册 Bean
- 依赖注入(DI)注解
- 生命周期注解(⭐重点)
- 懒加载与优先加载(⭐重点)
- 条件装配与环境配置
- Spring Boot 核心注解
- 其他高频实用注解
- 总结
1. 核心组件注解——声明一个 Bean
想让一个类被 Spring 管理,最简单的办法就是给它贴上对应的“标签”。
| 注解 | 作用 | 说明 |
|---|---|---|
@Component | 通用的组件注解,标注后类会被 Spring 扫描并加入容器 | 最基础的 Bean 注解 |
@Service | 标记服务层组件 | 语义更明确,本质同@Component |
@Repository | 标记持久层组件 | 额外自动转换数据库异常为 Spring 的DataAccessException |
@Controller/@RestController | 标记控制器 | @RestController=@Controller+@ResponseBody,返回 JSON 时常用 |
示例:
@ServicepublicclassUserServiceImplimplementsUserService{// ...}📌提示:
@Repository其实还承担了异常翻译功能,如果直接使用@Component标注 DAO 类,数据库异常不会自动转换成 Spring 的异常体系。
2. 配置与注册 Bean
当我们不能直接修改类(比如第三方库)或需要更灵活的 Bean 定义时,就用到下面这些注解。
| 注解 | 作用 | 常用场景 |
|---|---|---|
@Configuration | 声明一个配置类,内部可以用@Bean方法定义 Bean | 代替 XML 配置 |
@Bean | 方法级别,返回的对象会被纳入 Spring 容器 | 自定义组装 Bean,可通过initMethod/destroyMethod指定回调 |
@ComponentScan | 指定扫描包路径,自动发现组件 | 自定义扫描哪些包 |
@Import | 快速导入其他配置类或普通类 | 模块化配置 |
示例:
@ConfigurationpublicclassAppConfig{@Bean(name="dataSource",initMethod="start",destroyMethod="close")publicDataSourcedataSource(){returnnewBasicDataSource();}}3. 依赖注入(DI)注解
一个 Bean 想用另一个 Bean,只需要“告诉” Spring 你在哪里需要它。
| 注解 | 作用 |
|---|---|
@Autowired | 按类型自动注入,可标注在构造器、字段、setter 方法上 |
@Qualifier | 配合@Autowired,当有多个实现时按名称精确注入 |
@Primary | 当存在多个同类型 Bean 时,标注一个为首选 |
@Value | 注入外部属性值(如${server.port})或 SpEL 表达式 |
@Resource | 按名称注入(JSR-250),不常用但存在 |
示例:
@Autowired@Qualifier("userJdbcRepository")privateUserRepositoryuserRepository;⚠️注意:当存在多个同一接口的实现类时,
@Autowired会报错,此时要么使用@Qualifier,要么用@Primary指定默认。
4. 生命周期注解(⭐重点)
这是很多初学者容易忽略,但实际开发非常重要的部分。典型场景:初始化连接池、注册资源、销毁时清理线程等。
4.1@PostConstruct与@PreDestroy
- 来源:
javax.annotation(现 Jakarta EE) - 作用:
@PostConstruct:在 Bean 的依赖注入完成之后,正式可用之前执行@PreDestroy:容器销毁该 Bean之前执行清理工作(仅对单例有效)
使用示例:
@ComponentpublicclassCacheManager{@PostConstructpublicvoidinit(){// 初始化连接池、预加载缓存等System.out.println("CacheManager 初始化完成");}@PreDestroypublicvoidcleanup(){// 释放资源、关闭连接等System.out.println("CacheManager 即将销毁,执行清理");}}执行顺序:
构造方法 → 依赖注入(@Autowired)→@PostConstruct→ Bean 就绪
4.2@Bean的initMethod和destroyMethod
如果类不是你自己写的,没法加@PostConstruct注解,可以在@Bean中指定方法名。
@Bean(initMethod="start",destroyMethod="stop")publicThirdPartyServicethirdPartyService(){returnnewThirdPartyService();}destroyMethod默认推断close或shutdown方法,若要关闭推断可设为空字符串destroyMethod=""。
4.3 实现InitializingBean和DisposableBean接口(了解即可)
InitializingBean的afterPropertiesSet()等同于@PostConstructDisposableBean的destroy()等同于@PreDestroy
✅ 建议:优先使用
@PostConstruct/@PreDestroy,它们不与 Spring 强耦合,代码更干净。
4.4@Scope对生命周期的影响
@Scope("singleton"):默认,容器初始化时就创建(除非被@Lazy延迟),完整生命周期由 Spring 管理。@Scope("prototype"):每次获取都会新建,Spring 只负责创建,不负责销毁,因此@PreDestroy不会回调。
5. 懒加载与优先加载(⭐重点)
5.1@Lazy—— 懒加载
- 作用:让单例 Bean 的初始化推迟到第一次被调用时,而不是容器启动时。
- 可用于:
@Component、@Bean、@Autowired
示例:
@Service@LazypublicclassReportService{publicReportService(){System.out.println("ReportService 被实例化");}}效果:
- 容器启动时不会创建
ReportService,第一次调用它的方法时才会触发构造。 - 加快应用启动速度,适用于那些启动时不一定用到的重型服务。
注入点使用@Lazy:
@Autowired@LazyprivateHeavyServiceheavyService;此时注入的是一个代理对象,直到真正调用代理方法时才会从容器获取目标 Bean。
5.2@DependsOn—— 依赖优先
- 作用:强制指定当前 Bean 必须在指定的 Bean初始化完成之后才能创建。
- 适用场景:虽然没有直接注入,但存在静态注册或隐式依赖(例如 A 的静态代码块依赖 B 准备好)。
示例:
@Component@DependsOn("eventLogger")publicclassEventService{...}这样EventService无论如何都会等到eventLoggerBean 完全初始化后才开始创建。
5.3@Order与@Priority—— 控制顺序
@Order(org.springframework.core.annotation.Order):常用于同一接口的多个实现,控制它们作为List注入时的排序,值越小优先级越高。@Priority:JSR-250 标准,功能相似,也可用于选择首选 Bean。
常见用途:过滤器、拦截器、事件监听器的顺序。
@Component@Order(1)publicclassFirstFilterimplementsFilter{...}@Component@Order(2)publicclassSecondFilterimplementsFilter{...}5.4@Primary—— 优先选择
- 当存在多个同类型 Bean 时,标注
@Primary的 Bean 会作为@Autowired的默认选择。 @Qualifier的精确选择优先级高于@Primary。
6. 条件装配与环境配置
不同环境需要不同的 Bean?想让某些 Bean 只在特定条件下生效?下面这些注解帮你优雅实现。
| 注解 | 作用 |
|---|---|
@Profile | 根据激活的环境(application-{profile}.yml)决定是否加载 Bean |
@ConditionalOnClass | 类路径下存在指定类时才生效(Spring Boot 自动配置核心) |
@ConditionalOnMissingBean | 容器中缺少指定 Bean 时才会创建 |
@ConditionalOnProperty | 根据配置项的值(prefix.enabled=true)决定是否启用 |
@PropertySource | 加载指定的.properties文件 |
@ConfigurationProperties | 将配置前缀的属性批量绑定到类字段,需配合@EnableConfigurationProperties |
示例:
@Configuration@Profile("dev")publicclassDevDataSourceConfig{...}@Bean@ConditionalOnMissingBeanpublicCacheManagercacheManager(){returnnewConcurrentMapCacheManager();}7. Spring Boot 核心注解
| 注解 | 等价/作用 |
|---|---|
@SpringBootApplication | @Configuration+@EnableAutoConfiguration+@ComponentScan |
@EnableAutoConfiguration | 触发 Spring Boot 的自动配置机制 |
@RestControllerAdvice | 全局异常处理 +@ResponseBody,常配合@ExceptionHandler |
@SpringBootTest | 集成测试时加载完整 ApplicationContext |
Spring Boot 主类只要一个@SpringBootApplication就能启动自动扫描和自动配置。
8. 其他高频实用注解
Web 层
@GetMapping("/users/{id}")publicUsergetUser(@PathVariableLongid,@RequestParam(required=false)Stringname,@RequestBodyUseruser){...}常用搭配:@RequestMapping、@PostMapping、@PutMapping、@DeleteMapping、@RequestHeader、@CookieValue、@CrossOrigin。
异步与调度
@Async:方法异步执行,需在主类添加@EnableAsync。@Scheduled(fixedRate = 5000):定时任务,需添加@EnableScheduling。
事务与缓存
@Transactional:声明式事务,可用于类或方法。@Cacheable(value = "users", key = "#id")/@CacheEvict/@CachePut:配合缓存抽象(如 Redis)。
参数校验
@Valid/@Validated:触发参数校验。- 配合
@NotNull、@NotBlank、@Size等 JSR-303 注解。
示例:
@PostMappingpublicResultcreate(@Valid@RequestBodyUseruser){// ...}9. 总结
速查表帮你快速回忆:
| 类别 | 关键注解 | 一句话说明 |
|---|---|---|
| 生命周期 | @PostConstruct@PreDestroy@Bean(initMethod) | 控制 Bean 的初始化和销毁逻辑 |
| 懒加载 | @Lazy | 延迟创建直到首次使用 |
| 优先/顺序 | @DependsOn@Order@Priority@Primary | 控制 Bean 初始化顺序、注入优先级和排序 |
| 依赖注入 | @Autowired@Qualifier@Value | 自动装配成员 |
| 组件声明 | @Component@Service@Repository@Controller | 声明 Bean 并加入容器 |
| 条件装配 | @Profile@ConditionalOnClass等 | 按条件决定是否加载 Bean |
| 配置绑定 | @ConfigurationProperties | 将配置批量绑定到对象 |
| 核心入口 | @SpringBootApplication | Spring Boot 主类必备 |
掌握这些注解后,你会发现写 Spring 项目就像拼积木,干净又灵活。不妨收藏本教程,在遇到疑惑时快速查阅。如果还想深入了解某一类注解(比如事务传播机制、异步配置、缓存策略),欢迎在评论区留言,我会根据大家的反馈继续更新。
