今天我们来聊一下Spring Bean的生命周期,这是一个非常重要的问题,Spring Bean的生命周期也是比较复杂的。

IOC

IOC,控制反转概念需要提前了解一下,简单说就是把new对象的权利交给容器,所有的对象都由容器控制,称为控制反转

然后再通过依赖注入把它依赖的类注入给它。

Bean的生命周期

首先我们先来了解一下bean的作用域有哪些?

  • singleton: 在Spring IOC仅存在一个Bean实例,是Spring默认的bean作用域

  • prototype: 每次请求都会创建一个新的bean实例,即允许IOC中存在多个bean实例

  • request: 每次HTTP请求都会产生一个bean,该bean仅在HTTP request内有效

  • session:每一次HTTP请求都会产生一个新的bean,该bean在这个Session中共享

  • application:限定Bean的作用域为ServletContext的生命周期,该作用域仅适用于web的Spring WebApplicationContext环境

  • websocket: 限定Bean的作用域为WebSocket,该作用域仅适用于web的Spring WebApplicationContext环境

在Spring 中Bean的生命周期大致可以概况为:

实例化 -> 属性赋值 -> 初始化 -> 销毁

在Spring的Bean的生命周期种提供了很多的扩展点,常见的扩展接口有 InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware,InstantiationAwareBeanPostProcessor,BeanPostProcessor

其中的生命周期可以简单写为以下四步

  1. 实例化:首先,实例化一个Bean对象

  2. 属性赋值:为Bean对象设置属性和依赖

  3. 初始化:初始化,在完成后就可以被使用了

  4. 销毁:可以i通过第4步两种方法来添加配置

其中Bean的大致流程如图所示,展示了初始后的前置和后置过程,在实例化过程中也区分前置和后置过程,而初始化的前置和后置过程中主要是通过重写BeanPostProcessor中的postProcessBeforeInitialization和postProcessAfterInitialization实现的,销毁和初始也支持用户自定义方法。

下面我们继续来看在实例化和初始化时可以扩展的前置方法和后置方法。

运行结果

实例演示

实体类

public class User implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware {

    private String name;

    public User() {
System.out.println("1.2 User的无参构造, 实例化");
} /**
* 初始化方法
*/
public void initMethod() {
System.out.println("3.3. bean对象的初始化,调用指定的初始化方法");
} /**
* 销毁方法
*/
public void destroyMethod() {
System.out.println("4.2 bean对象的销毁,调用指定的销毁方法");
} public String getName() {
return name;
} public void setName(String name) {
System.out.println("2.1 设置User.name属性 设置属性");
this.name = name;
} @Override
public void setBeanName(String name) {
System.out.println("2.2调用BeanNameAware.setBeanName()方法");
} @Override
public void destroy() throws Exception {
System.out.println("4.1调用 DisposableBean.destroy() 方法");
} @Override
public void afterPropertiesSet() throws Exception {
System.out.println("3.2调用 InitializingBean.afterPropertiesSet() 方法");
} @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
User user = (User)applicationContext.getBean("user");
System.out.println(user);
System.out.println("调用ApplicationContextAware.setApplicationContext()");
}
}

实例化前后置代码

public class MyBeanInstant implements InstantiationAwareBeanPostProcessor {

    /**
* Spring 扩展点一、在bean实例化前和实例化后
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("1.1bean的前置处理器实例前 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
System.out.println(beanName + ": :" + beanClass);
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
} @Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("1.3bean的前置处理器实例后 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
System.out.println(beanName + ": :" + bean);
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
} @Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if ("user".equals(beanName)) {
System.out.println("1.4调用InstantiationAwareBeanPostProcessor.postProcessProperties()方法");
}
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}

初始化的前后置代码

public class MyBeanPost implements BeanPostProcessor {

    @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("3.1 bean的后置处理器初始化前 BeanPostProcessor.postProcessBeforeInitialization");
System.out.println(beanName + ": :" + bean);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("3.4 bean的后置处理器初始化后 BeanPostProcessor.postProcessAfterInitialization");
System.out.println(beanName + ": :" + bean);
System.out.println();
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
} }

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="myBeanPost" class="com.zly.ioc.life.MyBeanPost"/>
<bean id="myBeanInstant" class="com.zly.ioc.life.MyBeanInstant"/> <bean id="user" class="com.zly.ioc.life.User" scope="singleton" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="dy"/>
</bean>
</beans>

总结

本文主要是介绍了Bean的生命周期,简单介绍生命周期中的各种状态概念,以及各个阶段所执行的方法和操作。

Spring 之bean的生命周期的更多相关文章

  1. JAVA面试题:Spring中bean的生命周期

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

  2. 深入理解Spring中bean的生命周期

    [Spring中bean的生命周期] bean的生命周期 1.以ApplocationContext上下文单例模式装配bean为例,深入探讨bean的生命周期: (1).生命周期图: (2).具体事例 ...

  3. Spring中Bean的生命周期及其扩展点

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6106456.html Spring中Bean的管理是其最基本的功能,根据下面的图来了解Spr ...

  4. 简:Spring中Bean的生命周期及代码示例

    (重要:spring bean的生命周期. spring的bean周期,装配.看过spring 源码吗?(把容器启动过程说了一遍,xml解析,bean装载,bean缓存等)) 完整的生命周期概述(牢记 ...

  5. 面试Spring之bean的生命周期

    找工作的时候有些人会被问道Spring中Bean的生命周期,其实也就是考察一下对Spring是否熟悉,工作中很少用到其中的内容,那我们简单看一下. 在说明前可以思考一下Servlet的生命周期:实例化 ...

  6. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  7. 一分钟掌握Spring中bean的生命周期!

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean 的别名只能维持 ...

  8. Spring中bean的生命周期!

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

  9. 深究Spring中Bean的生命周期

    前言 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了<Spring in action>这本书,书上 ...

  10. Spring中 bean的生命周期

    为什么要了解Spring中 bean的生命周期? 有时候我们需要自定义bean的创建过程,因此了解Spring中 bean的生命周期非常重要. 二话不说先上图: 在谈具体流程之前先看看Spring官方 ...

随机推荐

  1. Python3程序捕获Ctrl+C终止信号

    技术背景 对于一些连续运行或者长时间运行的Python程序而言,如服务器的后端,或者是长时间运行的科学计算程序.当我们涉及到一些中途退出的操作时,比如使用Ctrl+C来退出正在运行的程序.这种场景的出 ...

  2. c++ 内存顺序

    搞懂无锁编程的重要一步是完全理解内存顺序! 本教程由作者和ChatGPT通力合作完成. 都有哪几种? c++的内存模型共有6种 memory_order_relaxed memory_order_co ...

  3. RealWorldCTF渗透赛第二期复现-ctfshow

    比赛概述 开始时间:2023年3月10日15时 环境保留时间:72小时 环境重置时间:20分钟 官方wp链接:Docs (feishu.cn) [本次复现跟着官方WP进行,只做记录学习之用] 0x1 ...

  4. 关于js通过修改行内样式来修改元素样式

    关于js通过修改行内样式来修改元素样式 1.当我们通过使用js来修改html元素的样式时,使用的方法是为元素添加行内样式, 此时的js样式是生效的,因为行内样式优先级高于类名 2.如果已有同属性的行内 ...

  5. Day05笔记

    01.数组类(了解) 1.目的:设计一个类,该类有数组的功能,可以存储数据,可以删除修改数据 2.设计核心数据 1.属性:指针(指向堆区空间),数组实际存储的元素个数,数组容量 2.方法:构造(开辟堆 ...

  6. CF1167G题解

    CF1167G题解 传送门 简化题意:数轴上有 n 个不相交且处于坐标为非负整数的单位正方形,给 m 个询问点,求出把这个点右侧的数轴逆时针旋转至与左侧相交时的角度. 首先,碰撞时只能有以下两种情况: ...

  7. Java面试——SQL语句题

    更多内容,前往IT-BLOG 一.行转列问题 现有表格A,按照以下格式排列: 姓名 收入类型 收入金额 Tom 年奖金 5w Tom 月工资 10k Jack 年奖金 8w Jack 月工资 12k ...

  8. ShardingSphere 数据分片之 Sharding-JDBC 深入理解

    更多内容,前往 IT-BLOG MySQL 的存储单位是 page[16kb],索引使用 B+Tree,深度为3(3次 IO便能查出数据).为了提高查询速度,存储单元中都存储的是索引的指针.MySQL ...

  9. Feeder 一款 Mac 上的 RSS 阅读器,更优雅地跟踪最新的新闻和博客文章

    Feeder 是一款 Mac 上的 RSS 阅读器,它可以帮助用户轻松地订阅和管理 RSS 源,让用户可以轻松地跟踪最新的新闻和博客文章. 下载: FeederMac ⇲ 详细了解 Feeder 的界 ...

  10. Win10系统总是锁屏关闭屏幕该怎么办?

    Win10系统总是锁屏关闭屏幕该怎么办? 转目前发现最早之帖,自脚本之家:https://www.jb51.net/os/win10/398451.html   使用Win10系统很长时间了,最近发现 ...