一文读懂 Bean的生命周期

简介: 一文读懂 Bean的生命周期

前言:

日月更替,周而复始,大自然中的任何生命都有着它的周期,比如蚂蚁的寿命只有几年,而乌龟的寿命却有几十年甚至上百年。


同理,在Spring框架中,Bean对象也有着它的生命周期,然而对于Bean对象的生命周期,我们并不是很清楚,因为Spring帮助我们管理了Bean对象,所以,掌握Bean的生命周期,并知晓Spring在每个阶段为我们做了哪些事情是非常有必要的。


Spring Bean的生命周期,你了解吗!好啦那我们一起来了解Bean生命周期!!!

一.什么是Bean的生命周期

bean的生命周期指的是:bean创建-->初始化-->销毁 的过程,bean的生命周期由容器进行管理,我们可以自定义bean的初始化和销毁方法来满足我们的需求,当容器在bean进行到当前生命周期的时候,来调用自定义的初始化和销毁方法。


在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。


相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程:

  1.  Spring 对bean 进行实例化。
  2.  Spring 将值和bean的引用注入到bean对应的属性中。
  3.  如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBean-Name()  方法。       (实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
  4.  如果bean 实现了BeanFactoryAware接口,Spring将调用setBeanFactory() 方法,将BeanFactory容器实例传入。     (实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
  5.  如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext() 方法,将bean所在的应用上下文的引用传入进来。(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )
  6.  如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessBeforeInitialization() 方法     (作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)
  7.  如果bean实现了InitializingBean接口,Spring将调用它们的after-PropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用。
  8.  如果bean实现了BeanPostProcessor接口,Spring将调用它们的post-ProcessAfterInitialization() 方法。    (作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )
  9.  此时, bean 已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁。
  10.  如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法。同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。


二.Bean的核心生命周期

虽然spring提供了大量Bean级生命周期接口和容器级生命空间接口来扩展bean的生命周期,但bean的核心生命周期只有四个阶段:

1.实例化 Instantiation


doCreateBean中调用createBeanInstance() 方法


2.属性赋值 Populate


doCreateBean中调用populateBean() 方法


3.初始化 Initialization


doCreateBean中调用initializeBean() 方法


4.销毁 Destruction


对于scope=singleton的Bean (prototype不会触发销毁),当容器关闭时,会触发bean的销毁。


三.Bean的单例与多例模式

3.1.什么是单例与多例

在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)

singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。

prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。

Spring bean默认是单例模式。

3.2.单例与多例bean的生命周期

  • 单实例下 bean的生命周期

容器启动——>初始化方法——>(容器关闭)销毁方法

  • 多实例下 bean的生命周期

容器启动——>调用bean——>初始化方法——>容器关闭(销毁方法不执行)

3.3.单例与多例的演示

单例模式:

package com.junlinyi.beanLife;
import java.util.List;
public class ParamAction {
  private int age;
  private String name;
  private List<String> hobby;
  private int num = 1;
  public ParamAction() {
    super();
  }
  public ParamAction(int age, String name, List<String> hobby) {
    super();
    this.age = age;
    this.name = name;
    this.hobby = hobby;
  }
  public void execute() {
    System.out.println("this.num=" + this.num++);
    System.out.println(this.name);
    System.out.println(this.age);
    System.out.println(this.hobby);
  }
}

测试一手:

package com.junlinyi.beanLife;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/*
 * spring bean的生命週期
 * spring bean的單例多例
 *
 */
public class Demo2 {
  // 体现单例与多例的区别
  @Test
  public void test1() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
    ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
    ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
    p1.execute();
    p2.execute();
//    单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;
    applicationContext.close();
  }
}

spring配置文件:

<!--    bean的生命周期-->
    <bean id="paramAction" class="com.junlinyi.beanLife.ParamAction">
        <constructor-arg name="name" value="三丰"></constructor-arg>
        <constructor-arg name="age" value="21"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>抽烟</value>
                <value>烫头</value>
                <value>大保健</value>
            </list>
        </constructor-arg>
    </bean>
</beans>

结果:

由于我们默认使用的是单例模式,所以在运行时出现了变量污染,num值变为2

Bean工厂:

package com.junlinyi.beanLife;
public class InstanceFactory {
  public void init() {
    System.out.println("初始化方法");
  }
  public void destroy() {
    System.out.println("销毁方法");
  }
  public void service() {
    System.out.println("业务方法");
  }
}

测试一手:

package com.junlinyi.beanLife;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/*
 * spring bean的生命週期
 * spring bean的單例多例
 *
 */
public class Demo2 {
  // 体现单例与多例的初始化的时间点 instanceFactory
  @Test
  public void test2() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
  }
}

spring配置上下文:

<bean id="instanceFactory" class="com.junlinyi.beanLife.InstanceFactory"
          scope="singleton" init-method="init" destroy-method="destroy"></bean>

.单例模式中的JavaBean是跟着Spring上下文初始化的,容器生成对象跟着生成,容器死亡,对象死亡

多例模式:

将spring配置文件中指定scope为prototype

<bean id="paramAction" class="com.junlinyi.beanLife.ParamAction" scope="prototype">
        <constructor-arg name="name" value="三丰"></constructor-arg>
        <constructor-arg name="age" value="21"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>抽烟</value>
                <value>烫头</value>
                <value>大保健</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="instanceFactory" class="com.xissl.beanLife.InstanceFactory"
          scope="prototype" init-method="init" destroy-method="destroy"></bean>

结果:

多例模式走的Javabean是使用时才会创建,销毁要跟着Jvm走:

   好啦,今天的分享就到这了,希望能够帮到你呢!😊😊  

目录
相关文章
|
存储 关系型数据库 MySQL
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
2035 0
|
10月前
|
存储 网络协议 Nacos
高效搭建Nacos:实现微服务的服务注册与配置中心
Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一款动态服务发现、配置管理和服务管理平台。它旨在帮助开发者更轻松地构建、部署和管理分布式系统,特别是在微服务架构中。
1688 82
高效搭建Nacos:实现微服务的服务注册与配置中心
|
消息中间件 缓存 Java
Spring Boot最经典的20道面试题,你都会了吗?
Spring Boot最经典的20道面试题,你都会了吗?
1335 0
|
机器学习/深度学习 数据采集 人工智能
机器学习在医疗诊断中的应用:开启智慧医疗新时代
【8月更文挑战第5天】机器学习革新医疗诊断,提升精准度与效率。通过分析医学影像和基因数据,实现疾病早期检测与个性化治疗。在药物研发中,加速候选药物筛选与优化过程。智能化患者管理及智能辅助决策系统进一步增强医疗服务质量。面对数据质量和隐私保护挑战,持续技术创新推动智慧医疗发展。
|
运维 Java Serverless
深度解析四大主流软件架构模型:单体架构、分布式应用、微服务与Serverless的优缺点及场景应用
深度解析四大主流软件架构模型:单体架构、分布式应用、微服务与Serverless的优缺点及场景应用
1578 0
|
敏捷开发 Java 测试技术
Spring源码解析 | 第一篇 :IntelliJ IDEA编译Spring5.3.x源码
Spring源码解析 | 第一篇 :IntelliJ IDEA编译Spring5.3.x源码
|
前端开发 Java 开发工具
推荐:一款Java开源的Springboot 即时通讯 IM 聊天系统
推荐:一款Java开源的Springboot 即时通讯 IM 聊天系统
570 0
|
对象存储 数据安全/隐私保护 开发者
.net core 阿里云接口之获取临时访问凭证
假设您是一个移动App开发者,希望使用阿里云OSS服务来保存App的终端用户数据,并且要保证每个App用户之间的数据隔离。此时,您可以使用STS授权用户直接访问OSS。 使用STS授权用户直接访问OSS的流程如下: ![image.png](https://ucc.alicdn.com/pic/developer-ecology/j2ygdazy447va_7d767aa1db4047778a7b5c568b5d7c11.png) ## 1、关于秘钥等信息的申请见如下链接 [使用STS临时访问凭证访问OSS](https://help.aliyun.com/zh/oss/developer
380 0
|
开发框架 JavaScript 开发者
什么是渐进式框架
渐进式框架(Progressive Framework)是一种软件开发框架的概念,它强调构建应用程序的方法是逐步增强(progressive enhancement)的,允许开发者根据项目的需求和复杂度选择性地使用框架提供的不同功能和特性。
|
存储 SQL 算法
数据脱敏技术与应用
数据脱敏技术与应用
数据脱敏技术与应用