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

2023.11.13 Spring Bean 的生命周期

目录

Spring 执行流程

Bean 的生命周期 

五个阶段

深入理解 Bean 初始化

实例理解 

总结梳理

经典面试题 


Spring 执行流程

Bean 的生命周期 

  • Spring 中 Bean 的生命周就是 Bean 在 Spring 中从创建到销毁的整个过程


五个阶段

1. 实例化 Bean

  • 为 Bean 对象分配内存空间

2. 设置属性

  • Spring 通过反射机制给 Bean 的属性赋值

3. Bean 初始化

  • 各种通知
  • 初始化前置方法
  • 初始化方法
  • 初始化后置方法

4. 使用 Bean

5. 销毁 Bean


深入理解 Bean 初始化

各种通知接口方法

  • BeanNameAware:允许 Bean 获取自己在容器中的名称
  • BeanFactoryAware:允许 Bean 获取对 Beanfactory的引用
  • ApplicationContextAware:允许 Bean 获取对 ApplicationContext 的引用

初始化前置方法

  • 该方法可以用于执行一些预处理操作,例如 设置一些默认属性或检查依赖关系

初始化方法

  • 如果使用注解方式,可以使用 @PostConstruct 注解来标记初始化方法
  • 如果使用 XML 配置方式,可以在 <bean> 标签中使用 init-method 属性来指定初始化方法的名称

初始化后置方法

  • 该方法可以用于执行一些后续操作,例如资源清理、启动定时任务等

注意:

  • 实例化和初始化是两个完全不同的过程
  • 实例化只是给Bean对象分配内存空间
  • 初始化则是将程序执行权从系统级别转到用户级别,执行用户添加的业务代码

实例理解 

  • 创建一个 BeanComponent 类

  • 在 Spring-config.xml 中使用 <bean> 标签将 BeanComponent 类的 Bean 对象注入到Spring 容器中

  •  BeanComponent 类设置 BeanNameAware 通知、两种初始化方法、销毁时执行的方法
  • sayHi 方法的创建是为了 使用 Bean 对象
import org.springframework.beans.factory.BeanNameAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;public class BeanComponent implements BeanNameAware {@Overridepublic void setBeanName(String s) {System.out.println( "BeanName ——> " + s + " 执行了通知");}/** xml 方式的初始化方法* */public void myInit() {System.out.println("XML 方式的初始化方法");}@PostConstructpublic void doPostConstruct() {System.out.println("注解方式的初始化方法");}public void sayHi() {System.out.println("执行 sayHi 方法");}/** 销毁时执行的方法* 此处使用注解的方式* */@PreDestroypublic void doPreDestroy() {System.out.println("销毁时的方法 已执行");}
}

注意:

  • 在启动类中获取 BeanComponent 类的 Bean 对象,并调用其 sayHi 方法,最后销毁容器
import com.java.demo.component.BeanComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {
//        因为 ApplicationContext 中没有销毁方法,所以此处使用 ClassPathXmlApplicationContextClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");BeanComponent beanComponent = context.getBean("beanComponent",BeanComponent.class);
//        调用 sayHi 方法,即使用该 Bean 对象beanComponent.sayHi();
//        将容器销毁context.destroy();}
}

运行结果:

  • 我们发现该执行结果,正好与我们的预期相符合

总结梳理

  • Spring 执行流程和 Bean 的生命周期 结合理解

  • 加载配置文件:Spring 容器会先加载配置文件,例如 XML 文件或注解配置,以获取Bean 的定义和相关的配置信息
  • 创建容器:根据配置文件中的定义,Spring 容器会创建一个应用上下文,也就是容器对象,用于管理 Bean 的生命周期
  • 实例化 Bean:Spring 容器根据配置文件中的定义,实例化 Bean 对象,这是通过调用Bean 的构造函数来完成的
  • 设置 Bean 属性:一旦 Bean 实例化完成,Spring 容器会通过调用 Bean 的 setter 方法或直接访问其字段,将文件中定义的属性值注入到 Bean 中
  • 调用 Bean 的初始化方法:如果 Bean 实现了 InitializingBean 接口,Spring 容器会在属性注入完成后调用其定义的初始化方法。同时如果在配置文件中指定了自定义的初始化方法。Spring 容器也会调用该方法
  • 使用 Bean:在 Bean 的初始化完成后,Spring 容器会将其放入容器中,供其他 Bean 或应用程序使用
  • 调用 Bean 的销毁方法:当 Spring 容器关闭时,它会销毁之前先释放的 Bean 资源,如果 Bean 实现了 DisposableBean 接口,容器会在销毁前调用其定义的销毁方法。同时,如果在配置文件中指定了自定义的销毁方法,Spring 容器也会调用该方法

经典面试题 

是否可以先 执行初始化 再 执行设置属性 ?

  • 不可以
  • 因为初始化方法中可能会用到设置后的属性

实例理解

@Controller
public class StudentController {//属性注入@Autowiredprivate Student student;//初始化@PostConstructpublic void init() {student.setName("xiaolin");}}
  • 如果此时先执行了初始化 init 方法
  • init 方法中需要使用属性注入后得到的 student 对象
  • 此时该 student 对象还未被 Spring 容器注入便被 init 方法进行修改
  • 上述过程,将直接引发空指针异常

相关文章:

  • SQL 撤销索引、表以及数据库||SQL CREATE DATABASE 语句||SQL CREATE TABLE 语句
  • 第十六章 文件服务
  • 无防御香港服务器如何防CC
  • 金蝶云星空表单插件获取控件值
  • 应届裁员,天胡开局——谈谈我的前端一年经历
  • day21_mysql
  • Linux内核分析(十四)--内存管理之malloc、free 实现原理
  • 深入了解HTTP与HTTPS关键差异与底层原理
  • 通过Python设置及读取PDF属性,轻松管理PDF文档
  • 阿里云国际站:应用实时监控服务
  • 使用Filebeat+Kafka+Logstash+Elasticsearch构建日志分析系统
  • spring-boot-starter-data-redis2.X连接redis7
  • 【Linux网络】1分钟使用shell脚本完成DNS主从解析服务器部署(适用于centos主机)
  • vue做的一个一点就转的转盘(音乐磁盘),点击停止时会在几秒内缓慢停止,再次点击按钮可以再次旋转,
  • 适用于WPF的设计模式
  • [译]如何构建服务器端web组件,为何要构建?
  • Android开源项目规范总结
  • Flex布局到底解决了什么问题
  • github指令
  • JS变量作用域
  • JS题目及答案整理
  • Laravel核心解读--Facades
  • php面试题 汇集2
  • springboot_database项目介绍
  • TCP拥塞控制
  • Vim Clutch | 面向脚踏板编程……
  • vue学习系列(二)vue-cli
  • webpack入门学习手记(二)
  • 从setTimeout-setInterval看JS线程
  • 第十八天-企业应用架构模式-基本模式
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 面试总结JavaScript篇
  • 前端面试题总结
  • 使用Gradle第一次构建Java程序
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • 移动端高清、多屏适配方案
  • $.ajax,axios,fetch三种ajax请求的区别
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (分布式缓存)Redis持久化
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • .net framework 4.0中如何 输出 form 的name属性。
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .net对接阿里云CSB服务
  • /etc/shadow字段详解
  • @Autowired标签与 @Resource标签 的区别
  • @Autowired注解的实现原理
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @modelattribute注解用postman测试怎么传参_接口测试之问题挖掘
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [HeadFrist-HTMLCSS学习笔记][第一章Web语言:开始了解HTML]
  • [HNOI2010]BUS 公交线路
  • [moka同学笔记]yii表单dropdownlist样式