当前位置: 首页 > 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作用域

相关文章:

  • C41-为什么要用指针
  • ubuntu环境下 基于Python 打包的 批量命令行可视化操作工具 GUI
  • Vue3项目使用ElDrawer后select方法不生效
  • 分布式 ID 生成的五种方法:优缺点与适用场景
  • 【C++】 —— 笔试刷题day_29
  • 界面控件DevExpress WinForms中文教程:Banded Grid View - API
  • 项目依赖版本修改
  • TensorFlow/Keras实现知识蒸馏案例
  • Tor推出Oniux新工具:为Linux应用提供网络流量匿名化
  • Graph Representation Learning【图最短路径优化/Node2vec/Deepwalk】
  • PR-2021
  • android 安装openwrt 安正步骤
  • Kotlin与Java的融合趋势:从互操作到云原生实践
  • 《解锁数字藏品交易系统的底层密码:区块链架构抉择》
  • Spring Boot循环依赖的陷阱与解决方案:如何打破“Bean创建死循环”?
  • 在 Visual Studio Code (VSCode) 中配置 MCP(Model Context Protocol)
  • 网络流量分析 | NetworkMiner
  • 【数据开发】埋点体系的讲解 - 埋点方式、原理、优缺点
  • 2025 家用投影新标杆:雷克赛恩 CyberPro1 如何重新定义客厅观影体验
  • 平衡智慧在日常生活中的落地实践:构建和谐生活的行动指南
  • 中办、国办关于持续推进城市更新行动的意见
  • 马上评|安排见义勇为学生补考,善意与善意的双向奔赴
  • 王征、解宁元、牛恺任西安市副市长
  • 2025财政观察|长三角“三公”经费普降,钱要用在刀刃上
  • 黄仕忠丨戏曲文献研究之回顾与展望
  • 中东睿评|特朗普中东三国行:喧嚣的形式与空洞的实质