【spring原理】Bean的作用域与生命周期

Bean的作用域

在编程中,Bean的作用域(Scope) 是指一个Bean对象的生命周期及其在应用上下文中的可见性。特别是在Spring框架中,Bean的作用域决定了一个Bean是如何被创建、共享和销毁的。以下是Spring中常用的Bean作用域及其特点:


1. Singleton(单例,默认作用域)

  • 描述: 整个Spring容器中仅存在一个共享的Bean实例。
  • 特点 :
    • 每次请求该Bean时,都会返回同一个实例。
    • 默认作用域,适用于无状态的Bean。
  • 应用场景: 大多数服务类、工具类、无状态组件。

2. Prototype(原型)

  • 描述: 每次请求时都会创建一个新的Bean实例。
  • 特点 :
    • 每次注入或通过ApplicationContext.getBean()获取时,都会返回一个新的对象。
    • Spring容器只负责创建实例,生命周期交由调用方管理。
  • 应用场景: 需要保持独立状态的组件,例如每个用户的会话对象。

3. Request

  • 描述: 在Web应用中,为每个HTTP请求创建一个新的Bean实例。
  • 特点 :
    • 每个HTTP请求会对应一个独立的Bean实例。
    • 仅在请求周期内有效,请求结束后自动销毁。
  • 应用场景: 与单个HTTP请求相关的状态信息。

4. Session

  • 描述: 在Web应用中,为每个HTTP会话创建一个Bean实例。
  • 特点 :
    • 在同一个HTTP会话中共享该Bean实例。
    • 会话结束后,Bean实例会被销毁。
  • 应用场景: 与用户会话相关的数据存储,例如用户购物车。

5. Application

  • 描述: 在Web应用的整个ServletContext范围内共享一个Bean实例。
  • 特点 :
    • 所有请求和会话共享同一个Bean实例。
  • 应用场景: 应用级别的全局资源,例如配置或缓存。

6. WebSocket(在Spring 4.0+引入)

  • 描述: 为每个WebSocket会话创建一个Bean实例。
  • 特点 :
    • 在WebSocket连接的整个生命周期内共享。
  • 应用场景: WebSocket交互中需要保持的会话状态。

使用示例

在Spring配置中可以通过@Scope注解指定Bean的作用域:

java 复制代码
@Component
@Scope("prototype")  // 定义为原型作用域
public class MyBean {
    // Bean的实现
}

或者在XML配置中:

XML 复制代码
<bean id="myBean" class="com.example.MyBean" scope="prototype"/>

作用域总结

  • 单例原型可以在所有Spring应用中使用。
  • RequestSessionApplicationWebSocket作用域主要用于Web应用。
  • 选择作用域时应根据Bean的用途和生命周期要求来决定。

Bean的生命周期

在Spring中,Bean的生命周期是指一个Bean从创建到销毁的整个过程。Spring容器通过多种机制对Bean的生命周期进行管理,包括初始化、依赖注入以及销毁等。以下是Spring中Bean生命周期的主要阶段及相关机制:


1. Bean的定义和加载

  • Spring通过配置文件(XML、Java配置类)或注解(如@Component@Bean)定义Bean。
  • Spring容器在启动时解析这些定义,并将其加载为BeanDefinition对象。

2. Bean的实例化

  • Spring容器根据BeanDefinition创建Bean实例。
  • 使用Java反射机制或工厂方法来实例化对象。

3. 属性赋值(依赖注入)

  • Spring通过**依赖注入(DI, Dependency Injection)**将Bean的依赖项设置到其属性中。
  • 注入方式包括构造器注入、Setter注入或通过字段注入(使用@Autowired等注解)。

4. Bean初始化

Bean初始化阶段包括以下步骤:

  1. 执行Aware接口的方法 (如果实现了相关接口):
    • BeanNameAware: 注入Bean的名称。
    • BeanFactoryAware: 注入BeanFactory对象。
    • ApplicationContextAware: 注入ApplicationContext对象。
  2. 执行BeanPostProcessorpostProcessBeforeInitialization方法 :
    • 容器会调用所有已注册的BeanPostProcessorpostProcessBeforeInitialization方法,允许在初始化之前对Bean进行处理。
  3. 调用初始化方法 :
    • 如果实现了InitializingBean接口,调用其afterPropertiesSet()方法。
    • 如果配置了自定义的初始化方法(通过@Bean(initMethod = "methodName")或XML配置中的init-method),则执行该方法。
  4. 执行BeanPostProcessorpostProcessAfterInitialization方法 :
    • 容器会调用所有已注册的BeanPostProcessorpostProcessAfterInitialization方法,允许在初始化之后对Bean进行进一步处理。

5. Bean的使用

  • Bean已经完全初始化,可以被应用程序使用。
  • 在整个生命周期中,根据Bean的作用域,决定是单例共享还是按需创建。

6. Bean的销毁

当容器关闭时,Bean进入销毁阶段:

  1. 调用DisposableBean接口的destroy()方法(如果实现了该接口)。
  2. 执行自定义销毁方法 :
    • 如果配置了自定义销毁方法(通过@Bean(destroyMethod = "methodName")或XML配置中的destroy-method),则执行该方法。
  3. 释放资源 :
    • Spring容器释放与Bean相关的所有资源。

Bean生命周期示意图

  1. 定义和加载 →
  2. 实例化 →
  3. 属性赋值(依赖注入) →
  4. 初始化(Aware接口、BeanPostProcessor、初始化方法) →
  5. 使用 →
  6. 销毁(DisposableBean、自定义销毁方法)

示例代码

使用注解的生命周期管理
java 复制代码
@Component
public class MyBean implements InitializingBean, DisposableBean {
    @Override
    public void afterPropertiesSet() {
        System.out.println("InitializingBean: afterPropertiesSet called");
    }

    @Override
    public void destroy() {
        System.out.println("DisposableBean: destroy called");
    }

    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct: init method called");
    }

    @PreDestroy
    public void cleanup() {
        System.out.println("@PreDestroy: cleanup method called");
    }
}

总结

Spring中的Bean生命周期可以通过接口、注解和配置灵活管理,关键阶段包括实例化、依赖注入、初始化和销毁。开发者可以在这些阶段自定义行为,以满足特定需求,例如资源初始化和清理工作。

相关推荐
LUCIAZZZ43 分钟前
简单的SQL语句的快速复习
java·数据库·sql
komo莫莫da1 小时前
寒假刷题Day19
java·开发语言
计算机-秋大田2 小时前
基于微信小程序的电子竞技信息交流平台设计与实现(LW+源码+讲解)
spring boot·后端·微信小程序·小程序·课程设计
S-X-S2 小时前
算法总结-数组/字符串
java·数据结构·算法
linwq82 小时前
设计模式学习(二)
java·学习·设计模式
桦说编程3 小时前
CompletableFuture 超时功能有大坑!使用不当直接生产事故!
java·性能优化·函数式编程·并发编程
@_@哆啦A梦3 小时前
Redis 基础命令
java·数据库·redis
字节全栈_rJF4 小时前
性能测试 —— Tomcat监控与调优:status页监控_tomcat 自带监控
java·tomcat
爱编程的小新☆5 小时前
Java篇之继承
java·开发语言
gentle coder5 小时前
Redis_Redission的入门案例、多主案例搭建、分布式锁进行加锁、解锁底层源码解析
java·redis·分布式