当前位置: 首页 > news >正文

Spring bean 的生命周期、注入方式和作用域

一、Spring Bean的生命周期

Spring Bean的生命周期是指从Bean的定义加载到最终销毁的整个过程,Spring框架在每个阶段都提供了钩子方法,允许开发者在特定时机执行自定义逻辑。

1. Bean定义加载阶段

容器启动时加载配置(XML/注解/JavaConfig),解析@Component、@Bean等注解或XML配置,生成BeanDefinition。BeanDefinition是描述Bean的元数据对象,包含类名、作用域、初始化方法、属性值、依赖关系等信息。

2. Bean实例化阶段

Spring容器根据BeanDefinition创建Bean实例,通常通过反射机制实现。例如,对于UserService类,Spring会使用类似Class.forName("com.example.UserService").newInstance()的方式创建对象实例。

3. 属性填充阶段

在实例化之后,Spring会将依赖的其他Bean注入到当前Bean中。例如,如果UserService依赖于UserRepository,Spring会查找并将UserRepository的实例注入到UserService中。

4. 初始化回调阶段

Bean可以实现InitializingBean接口,在afterPropertiesSet方法中编写初始化逻辑。也可以通过以下方式实现初始化回调:

public class ExampleBean implements InitializingBean {public void afterPropertiesSet() {// 初始化逻辑}
}

或使用@PostConstruct注解标记初始化方法420。

5. 销毁阶段

在容器关闭时,Spring会调用实现了DisposableBean接口的Bean的destroy()方法,或使用@PreDestroy注解标记的方法执行清理工作。

二、Spring Bean的注入方式

Spring支持多种依赖注入方式,每种方式有其适用场景和优缺点。

1. 构造器注入(Constructor Injection)

通过类的构造函数注入依赖,是Spring官方推荐的方式,尤其是在Spring 4.3及以上版本中。

特点:

  • 不可变性:依赖项在对象创建时注入,之后不可更改
  • 强依赖:明确表示类的依赖关系
  • 易于测试:便于单元测试
  • 避免循环依赖:如果存在循环依赖,Spring会抛出异常

示例代码:

@Service
public class UserService {private final UserRepository userRepository;@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}

2. Setter注入(Setter Injection)

通过setter方法注入依赖,适用于可选依赖或需要在对象创建后进行依赖设置的情况。

特点:

  • 灵活性高:支持可选依赖
  • 解决循环依赖:Spring容器可处理Setter注入的循环依赖
  • 向后兼容:适合逐步迁移旧代码到依赖注入模式

示例代码:

@Service
public class OrderService {private PaymentProcessor paymentProcessor;@Autowiredpublic void setPaymentProcessor(PaymentProcessor paymentProcessor) {this.paymentProcessor = paymentProcessor;}
}

3. 字段注入(Field Injection)

直接在类的字段上使用注解注入依赖,虽然代码简洁但不被推荐。

特点:

  • 代码简洁
  • 可能导致循环依赖
  • 不利于单元测试
  • 无法使用final修饰符

4. 方法注入(Method Injection)

一种特殊的注入方式,主要用于解决单例Bean中需要原型Bean的情况。

实现方式:

  • 实现ApplicationContextAware接口,手动获取Bean
  • 使用@Lookup注解标记方法

示例代码:

@Component
public class CommandManager implements ApplicationContextAware {private ApplicationContext applicationContext;public Object process(Map<String, Object> params) {Command command = createCommand();command.setStateMap(params);return command.execute();}protected Command createCommand() {return applicationContext.getBean(Command.class);}
}

三、Spring Bean的作用域

Spring Bean的作用域决定了Bean实例的创建方式和生命周期管理。

1. 标准作用域

作用域描述适用场景
singleton整个容器中只有一个实例无状态Bean,Spring默认作用域
prototype每次请求都创建新实例有状态Bean

2. Web相关作用域

作用域描述适用场景
request每个HTTP请求创建一个新实例Web请求处理
session每个用户会话创建一个实例用户会话数据
applicationServletContext生命周期全局应用数据

3. 自定义作用域

Spring允许开发者创建自定义作用域,例如线程级作用域或多租户系统中的租户级作用域22。

实现步骤:

  1. 实现Scope接口
  2. 注册自定义作用域到容器
  3. 在Bean定义中使用自定义作用域

4. 作用域与生命周期的关系

不同作用域的Bean在生命周期管理上有显著差异:

  • singleton Bean‌:在容器启动时创建,容器关闭时销毁
  • prototype Bean‌:每次请求时创建,由调用者负责销毁
  • request/session Bean‌:在请求/会话开始时创建,在请求/会话结束时销毁

四、最佳实践与最新特性(2025)

1. 注入方式选择

  • 强制依赖‌:优先使用构造器注入
  • 可选依赖‌:考虑使用Setter注入
  • 避免使用‌:字段注入,特别是在新项目中

2. 生命周期管理

  • 使用@PostConstruct@PreDestroy注解管理初始化和销毁逻辑,而不是实现InitializingBeanDisposableBean接口
  • 对于持有外部资源(如数据库连接)的Bean,务必实现销毁逻辑

3. 作用域选择

  • 默认使用singleton作用域
  • 有状态对象使用prototype作用域
  • Web相关数据使用request/session作用域
http://www.xdnf.cn/news/492013.html

相关文章:

  • LangGraph 官方文档翻译 - 快速入门及示例教程(聊天、工具、记忆、人工干预、自定义状态、时间回溯)
  • 【全解析】EN18031标准下的SSM安全存储机制
  • AI专题 | 金融业AI转型:细分业务场景的AI应用
  • Kotlin与Java的融合趋势:从互操作到云原生实践
  • 张量积表示 [Tensor Product Representation, TPR]
  • 指针在访问越界时不崩溃,但是释放的时候发生崩溃,底层原因分析
  • 【视觉任务】深度估计(Depth Estimation)介绍(2025年更新)
  • 【AT32】 AT32 移植 Freemodbus 主站
  • 亲缘半相合供者
  • 第二十次博客打卡
  • 10G 集成 4 口网口连接器的核心优势
  • FC7300 CAN MCAL 配置引导
  • SVMSPro平台如何获取HLS视频流
  • 差分探头为什么要选择使用屏蔽双绞线
  • DeepSeek基础:PPO、DPO、GRPO概念详解
  • Cursor 中的AI模型到底怎么选 ?
  • 城市综合管廊监测与维护一体化解决方案
  • MinerU本地化部署可视化界面
  • QT6 源(104)篇一:阅读与注释QAction,其是窗体菜单栏与工具栏里的菜单项,先给出属性测试
  • 基于MNIST数据集的手写数字识别(CNN)
  • 产品经理如何做好需求管理
  • 论文浅尝 | HOLMES:面向大语言模型多跳问答的超关系知识图谱方法(ACL2024)
  • 用GPU训练模型的那些事:PyTorch 多卡训练实战
  • 蓝牙AVCTP协议概述
  • 【软考 霍夫曼编码的文档压缩比】
  • 【数据结构】二分查找-LeftRightmost
  • 英语六级备考-阅读篇
  • 25年2月通信基础知识补充2:延迟对齐调制、常见卫星移动速度
  • python中 raise notimplementederror有什么功能,如何使用
  • 类模板的简单实例