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 @Bean 的 initMethod 和 destroyMethod

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

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

4.3 实现 InitializingBean 和 DisposableBean 接口(了解即可)

  • InitializingBean 的 afterPropertiesSet() 等同于 @PostConstruct
  • DisposableBean 的 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
@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 —— 控制顺序

  • @Order(org.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将配置批量绑定到对象
核心入口@SpringBootApplicationSpring Boot 主类必备

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


Logo

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

更多推荐