Spring & Spring Boot 常用注解详解:生命周期、懒加载、优先加载与实用技巧

前言

在 Spring 和 Spring Boot 开发中,注解几乎是“每天必打交道”的伙伴。它们像魔法一样,可以帮你声明 Bean、管理依赖、控制加载顺序、处理事务、配置环境……但注解多了也容易混淆。本教程将按功能模块,带你系统梳理 Spring 生态中最常用的注解,尤其会重点讲解生命周期、懒加载和优先加载相关的那些“容易踩坑”的注解。全文配合示例,希望对你的日常开发有所助益。


目录

  1. 核心组件注解——声明一个 Bean
  2. 配置与注册 Bean
  3. 依赖注入(DI)注解
  4. 生命周期注解(⭐重点)
  5. 懒加载与优先加载(⭐重点)
  6. 条件装配与环境配置
  7. Spring Boot 核心注解
  8. 其他高频实用注解
  9. 总结

1. 核心组件注解——声明一个 Bean

想让一个类被 Spring 管理,最简单的办法就是给它贴上对应的“标签”。

注解 作用 说明
@Component 通用的组件注解,标注后类会被 Spring 扫描并加入容器 最基础的 Bean 注解
@Service 标记服务层组件 语义更明确,本质同 @Component
@Repository 标记持久层组件 额外自动转换数据库异常为 Spring 的 DataAccessException
@Controller / @RestController 标记控制器 @RestController = @Controller + @ResponseBody,返回 JSON 时常用

示例:

@Service
public class UserServiceImpl implements UserService {
    // ...
}

📌 提示@Repository 其实还承担了异常翻译功能,如果直接使用 @Component 标注 DAO 类,数据库异常不会自动转换成 Spring 的异常体系。


2. 配置与注册 Bean

当我们不能直接修改类(比如第三方库)或需要更灵活的 Bean 定义时,就用到下面这些注解。

注解 作用 常用场景
@Configuration 声明一个配置类,内部可以用 @Bean 方法定义 Bean 代替 XML 配置
@Bean 方法级别,返回的对象会被纳入 Spring 容器 自定义组装 Bean,可通过 initMethod / destroyMethod 指定回调
@ComponentScan 指定扫描包路径,自动发现组件 自定义扫描哪些包
@Import 快速导入其他配置类或普通类 模块化配置

示例:

@Configuration
public class AppConfig {
    @Bean(name = "dataSource", initMethod = "start", destroyMethod = "close")
    public DataSource dataSource() {
        return new BasicDataSource();
    }
}

3. 依赖注入(DI)注解

一个 Bean 想用另一个 Bean,只需要“告诉” Spring 你在哪里需要它。

注解 作用
@Autowired 按类型自动注入,可标注在构造器、字段、setter 方法上
@Qualifier 配合 @Autowired,当有多个实现时按名称精确注入
@Primary 当存在多个同类型 Bean 时,标注一个为首选
@Value 注入外部属性值(如 ${server.port})或 SpEL 表达式
@Resource 按名称注入(JSR-250),不常用但存在

示例:

@Autowired
@Qualifier("userJdbcRepository")
private UserRepository userRepository;

⚠️ 注意:当存在多个同一接口的实现类时,@Autowired 会报错,此时要么使用 @Qualifier,要么用 @Primary 指定默认。


4. 生命周期注解(⭐重点)

这是很多初学者容易忽略,但实际开发非常重要的部分。典型场景:初始化连接池、注册资源、销毁时清理线程等。

4.1 @PostConstruct@PreDestroy

  • 来源javax.annotation(现 Jakarta EE)
  • 作用
    • @PostConstruct:在 Bean 的依赖注入完成之后,正式可用之前执行
    • @PreDestroy:容器销毁该 Bean 之前执行清理工作(仅对单例有效)

使用示例:

@Component
public class CacheManager {

    @PostConstruct
    public void init() {
        // 初始化连接池、预加载缓存等
        System.out.println("CacheManager 初始化完成");
    }

    @PreDestroy
    public void cleanup() {
        // 释放资源、关闭连接等
        System.out.println("CacheManager 即将销毁,执行清理");
    }
}

执行顺序:
构造方法 → 依赖注入(@Autowired)→ @PostConstruct → Bean 就绪

4.2 @BeaninitMethoddestroyMethod

如果类不是你自己写的,没法加 @PostConstruct 注解,可以在 @Bean 中指定方法名。

@Bean(initMethod = "start", destroyMethod = "stop")
public ThirdPartyService thirdPartyService() {
    return new ThirdPartyService();
}
  • destroyMethod 默认推断 closeshutdown 方法,若要关闭推断可设为空字符串 destroyMethod=""

4.3 实现 InitializingBeanDisposableBean 接口(了解即可)

  • InitializingBeanafterPropertiesSet() 等同于 @PostConstruct
  • DisposableBeandestroy() 等同于 @PreDestroy

✅ 建议:优先使用 @PostConstruct / @PreDestroy,它们不与 Spring 强耦合,代码更干净。

4.4 @Scope 对生命周期的影响

  • @Scope("singleton"):默认,容器初始化时就创建(除非被 @Lazy 延迟),完整生命周期由 Spring 管理。
  • @Scope("prototype"):每次获取都会新建,Spring 只负责创建,不负责销毁,因此 @PreDestroy 不会回调。

5. 懒加载与优先加载(⭐重点)

5.1 @Lazy —— 懒加载

  • 作用:让单例 Bean 的初始化推迟到第一次被调用时,而不是容器启动时。
  • 可用于@Component@Bean@Autowired

示例:

@Service
@Lazy
public class ReportService {
    public ReportService() {
        System.out.println("ReportService 被实例化");
    }
}

效果

  • 容器启动时不会创建 ReportService,第一次调用它的方法时才会触发构造。
  • 加快应用启动速度,适用于那些启动时不一定用到的重型服务。

注入点使用 @Lazy

@Autowired
@Lazy
private HeavyService heavyService;

此时注入的是一个代理对象,直到真正调用代理方法时才会从容器获取目标 Bean。

5.2 @DependsOn —— 依赖优先

  • 作用:强制指定当前 Bean 必须在指定的 Bean 初始化完成之后才能创建。
  • 适用场景:虽然没有直接注入,但存在静态注册或隐式依赖(例如 A 的静态代码块依赖 B 准备好)。

示例:

@Component
@DependsOn("eventLogger")
public class EventService { ... }

这样 EventService 无论如何都会等到 eventLogger Bean 完全初始化后才开始创建。

5.3 @Order@Priority —— 控制顺序

  • @Orderorg.springframework.core.annotation.Order):常用于同一接口的多个实现,控制它们作为 List 注入时的排序,值越小优先级越高
  • @Priority:JSR-250 标准,功能相似,也可用于选择首选 Bean。

常见用途:过滤器、拦截器、事件监听器的顺序。

@Component
@Order(1)
public class FirstFilter implements Filter { ... }

@Component
@Order(2)
public class SecondFilter implements Filter { ... }

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")
public class DevDataSourceConfig { ... }

@Bean
@ConditionalOnMissingBean
public CacheManager cacheManager() {
    return new ConcurrentMapCacheManager();
}

7. Spring Boot 核心注解

注解 等价/作用
@SpringBootApplication @Configuration + @EnableAutoConfiguration + @ComponentScan
@EnableAutoConfiguration 触发 Spring Boot 的自动配置机制
@RestControllerAdvice 全局异常处理 + @ResponseBody,常配合 @ExceptionHandler
@SpringBootTest 集成测试时加载完整 ApplicationContext

Spring Boot 主类只要一个 @SpringBootApplication 就能启动自动扫描和自动配置。


8. 其他高频实用注解

Web 层

@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id,
                    @RequestParam(required = false) String name,
                    @RequestBody User user) { ... }

常用搭配:@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 注解。

示例:

@PostMapping
public Result create(@Valid @RequestBody User user) {
    // ...
}

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 项目就像拼积木,干净又灵活。不妨收藏本教程,在遇到疑惑时快速查阅。如果还想深入了解某一类注解(比如事务传播机制、异步配置、缓存策略),欢迎在评论区留言,我会根据大家的反馈继续更新。


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐