SpringBean生命周期之五、七、十步(详解)

目录

前提

一.Bean的完整周期

1.1什么是Bean的生命周期

二.SpringBean的五步分析法

2.1理论分析 

2.2代码实现

三.Bean周期之七步分析法

3.1理论分析

3.2代码实现

四.Bean生命周期之十步分析法

4.1理论分析

4.2代码实现

五.总结

5.1五步、七步、十步的差别

5.2SpringBean周期的概况


前提

        在学习Spring的对象注入之后,我们可以了解一下,Bean对象的生命周期,更好学习到在Spring容器里,Bean经历了什么!        

ps:在日常里SrpingBean周期并不会使用,但是在面试当中经常出现!

一.Bean的完整周期

1.1什么是Bean的生命周期

      在传统java应用程序里,bean是new进行实例化的,若不会使用了,则会由Java自动进行垃圾回收!

Spring Bean 的生命周期在不同的文献和说明中可能会被划分为不同的步骤,比如五步、七步或十步。这种不同的划分方式主要是为了更详细地描述 Bean 的生命周期过程,以便开发人员更好地理解和控制 Bean 的创建、初始化和销毁过程。

  1. 五步划分:通常指的是 BeanFactory 的生命周期,包括 BeanFactory 的实例化、配置元数据定位、Bean 的定义解析、Bean 的注册和实例化。这种划分方式主要关注 Spring 容器本身的初始化过程。

  2. 七步划分:在七步划分中,通常会将 BeanPostProcessor 的前置处理和后置处理分别作为两个独立的步骤,这样可以更清晰地表达 BeanPostProcessor 在 Bean 生命周期中的作用。

  3. 十步划分:这种划分方式可能会更加详细地描述 Bean 的初始化和销毁过程,包括 BeanFactory 的初始化、Bean 的实例化、设置属性、BeanPostProcessor 的前置处理、初始化方法调用、BeanPostProcessor 的后置处理、Bean 可使用阶段、销毁前处理、销毁方法调用和销毁后处理。这种划分方式提供了更加详细的生命周期过程描述,有助于开发人员深入理解 Bean 的各个阶段。

本文由浅到深,步步剖析!

二.SpringBean的五步分析法

2.1理论分析 

所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,Bean的五步生命周期简略分为以下五部分:

  1. 实例化 Bean(为 Bean 分配内存空间,调用无参构造方法)
  2. 设置属性(Bean 注⼊和装配,调用set方法)
  3. Bean 初始化(会调用各种各样的方法,不需要仔细了解)
  4. 使⽤ Bean
  5. 销毁 Bean(Spring会自动调用destroy方法,当然也可以使用自己定义该方法)

图中,初始化和销毁Bean其实还需要实现几个接口、重写方法,但这是七步分析和十步分析当中学习,我们暂且不提,后期的七步分析和十步分析就是剖析这些接口方法。

Bean 初始化:
  1. 实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAware、 ApplicationContextAware 的接⼝⽅法;
  2. 执⾏ BeanPostProcessor 初始化前置⽅法;
  3. 执⾏ @PostConstruct 初始化⽅法,依赖注⼊操作之后被执⾏;
  4. 执⾏⾃⼰指定的 init-method ⽅法(该方法自己定义)
  5. 执⾏ BeanPostProcessor 初始化后置⽅法。

2.2代码实现

        在Spring容器里,会自动管理Bean的初始化、设置属性、使用、销毁各个阶段,当Spring容器销毁时,会自动销毁容器内所有的Bean,会自动调用Bean的destroy方法,但有两种情况不会调用。

  1. 如果Bean类实现了DisposableBean接口,容器会调用其destroy()方法
  2. 如果在Spring配置文件中配置了destroy-method属性,容器会调用指定的销毁方法。

接下来的代码我们使用第二种方式,将具体流程呈现:

User类:

public class User {
        private String username;

        public void setUsername(String username) {
            System.out.println("第二步:给对象的属性赋值");
            this.username = username;
        }

        public User() {
            System.out.println("第一步:实例化Bean,无参数构造方法执行了");
        }

        // 初始化Bean,为了呈现流程,自己写
        public void initBean(){
            System.out.println("第三步:初始化Bean");
        }

        // 销毁Bean,为了呈现流程,自己定义
        public void destroyBean(){
            System.out.println("第五步:销毁Bean");
        }

        @Override
        public String toString() {
            return "User{" +
                    "username='" + username + '\'' +
                    '}';
        }

}

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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
    <bean id="user" class="com.school_ee.test.User"
          init-method="initBean" destroy-method="destroyBean">
             <!-- initBean和destroyBean是User类中自己定义的方法,会自动调用 -->
        <!--给属性赋值-->
        <property name="username" value="张三"/>
    </bean>
</beans>

接下来测试类测试:

public void init(){
        ApplicationContext applicationContext = new         ClassPathXmlApplicationContext("Spring.xml");
        User user = applicationContext.getBean("user", User.class);
        System.out.println("第四步:使用Bean");
        //为了呈现关闭流程、手动关闭Spring容器
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }

执行结果:

注意点:

  1. 只有正常关闭spring容器(调用close方法),bean的销毁方法才会被调用

  2. ClassPathXmlApplicationContext类才有close()方法,ApplicationContext中没有。

  3. 如果不希望Spring自动创建和销毁,可使配置文件中的init-method指定初始化方法,destroy-method指定销毁方法。

三.Bean周期之七步分析法

3.1理论分析

 

        所谓的七步分析,是在五步法的Bean初始化阶段将 BeanPostProcessor接口 的前置处理和后置处理分别作为两个独立的步骤。就是更加清晰的表达BeanPostProcessor 在 Bean 生命周期中的作用。

        BeanPostProcessor 接口的作用:Spring 框架提供的一个扩展点,用于在 Spring 容器实例化 Bean 和将 Bean 实例化到容器中之间的过程中,对 Bean 进行额外的处理。定义了前置处理方法和后置处理方法:

  1. 前置处理(postProcessBeforeInitialization):

    • 在 Bean 实例化后、依赖注入后,以及自定义初始化方法调用之前执行。
    • 可以用于对 Bean 进行额外的初始化操作,或者修改 Bean 的属性值。
    • 常见的使用场景包括对 Bean 进行动态代理、添加日志记录、进行安全检查等。
  2. 后置处理(postProcessAfterInitialization):

    • 在 Bean 自定义初始化方法调用后执行,也就是 Bean 已经完全初始化完成后执行。
    • 可以用于对 Bean 进行额外的操作,或者对已初始化的 Bean 进行后续处理。
    • 常见的使用场景包括对 Bean 进行缓存、注册监听器、执行特定的业务逻辑等。

3.2代码实现

        为了更好展示流程,我们自定义类实现 BeanPostProcessor 接口,并重写其中的postProcessBeforeInitialization方法和postProcessAfterInitialization方法。

自定义类实现接口:

package com.bjpowernode.spring.test;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
 
public class LogBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean初始化前,处理器的before方法执行");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化结束,处理器的after方法执行");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

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="user" class="com.school_ee.test.User"
          init-method="initBean" destroy-method="destroyBean">
                     <!-- initBean和destroyBean是User类中自己定义的方法,会自动调用 -->
        <!--给属性赋值-->
        <property name="username" value="张三"/>
    </bean>

    <!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。-->
    <bean class="com.school_ee.test.LogBeanPostProcessor" />
</beans>

测试文件不需要改变,直接上结果:

从测试结果中,我们可以发现,的的确确从初始化前后执行Before方法和after方法。

四.Bean生命周期之十步分析法

4.1理论分析

 

和七步分析做对比,额外的三步:

  1. 检查Bean是否实现了Aware相关的接口
    • BeanNameAware 接口回调 ,目的:允许 bean 在初始化阶段获取自身在 Spring 容器中的名字
    • BeanFactoryAware 接口回调,目的:允许 bean 在初始化阶段获取对 Spring 容器的引用
  2. 检查Bean是否实现了InitializingBean接口,Spring 在 bean 初始化完成后会自动调用 afterPropertiesSet() 方法,执行一些数据初始化、资源加载、连接数据库等必要操作
  3. 检查Bean是否实现了DisposableBean接口,Spring 容器在销毁该 bean 时会调用其 destroy() 方法,从而允许 bean 执行一些资源释放或者清理操作。

结论:检查你这个Bean是否实现了某些特定的接口,如果实现了这些接口,则Spring容器会调用这个接口中的方法!

4.2代码实现

user类实现所有接口的代码: 

package com.bjpowernode.spring.bean;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
 
 
public class User implements
        BeanNameAware, BeanClassLoaderAware, BeanFactoryAware,
        InitializingBean, DisposableBean{
    private String username;
 
    public void setUsername(String username) {
        System.out.println("第二步:给对象的属性赋值");
        this.username = username;
    }
 
    public User() {
        System.out.println("第一步:实例化Bean,无参数构造方法执行了");
    }
 
    // 初始化Bean,需要自己写,自己配,方法名随意
    public void initBean(){
        System.out.println("第四步:初始化Bean");
    }
 
    // 销毁Bean,需要自己写,自己配,方法名随意
    public void destroyBean(){
        System.out.println("第七步:销毁Bean");
    }
 
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }
 
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("类加载器:" + classLoader);
    }
 
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Bean工厂:" + beanFactory);
    }
 
    @Override
    public void setBeanName(String name) {
        System.out.println("Bean的名字:" + name);
    }
 
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy方法执行了");
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet方法执行了");
    }
}

xml配置文件不变,测试类不变,直接测试:

五.总结

5.1五步、七步、十步的差别

标准的五步:实例化--->设置属性--->初始化---->使用Bean---->销毁Bean

七步:实例化--->设置属性--->前置处理----->初始化----->后置处理---->使用Bean---->销毁Bean

十步:实例化--->设置属性--->Aware接口实现--->前置处理----->InitializingBean接口--->初始化----->后置处理---->使用Bean---->DisposableBean接口---->销毁Bean

5.2SpringBean周期的概况

(1)Spring其实就是一个管理Bean对象的工厂,它负责对象的创建,对象的销毁等。

(2)所谓的生命周期就是:对象从创建开始到最终销毁的整个过程。

(3)为什么要知道Bean的生命周期?

  1. 定制 Bean 的初始化和销毁过程:通过了解 Bean 的生命周期,开发人员可以在 Bean 初始化之前或销毁之后执行特定的操作,比如资源的初始化和释放、日志记录、权限检查等。

  2. 解决依赖关系问题:在了解 Bean 的生命周期的过程中,可以更好地理解 Spring 容器是如何管理 Bean 的创建、依赖注入以及销毁的,有助于解决 Bean 之间的依赖关系问题。

  3. 优化性能:了解 Bean 的生命周期可以帮助开发人员避免一些不必要的操作,从而提高系统的性能。比如在 Bean 的初始化阶段进行一些耗时操作,可能会影响系统的启动速度。

  4. 排查问题:当出现一些意外情况或 Bug 时,了解 Bean 的生命周期可以帮助开发人员更快地定位问题所在,从而更容易地进行排查和修复。

注:上述的Bean周期了解即可,在Spring容器里已经实现!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/510649.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IPC 进程间通信

IPC InterProcess Communication The concept of IPC Each process has a differnt user addess space,and local variables 各自看不见,so 进程间通信 need kernel(内核), so a buffer is opened in the kernel,process 1 copies data from user space to this buffer,and …

易语言控件绑定数据库

易语言是一门中文编程语言&#xff0c;由国人开发&#xff0c;虽然比较冷门&#xff0c;但是在有些场合却非常流行&#xff0c;比如自动化脚本&#xff0c;还有开发外挂。 在易语言中&#xff0c;只要控件的属性里有数据源的都可以与数据库的数据绑定&#xff0c;以下将演示易…

消息存储与同步策略设计

消息存储与同步策略 https://github.com/robinfoxnan/BirdTalkServer 思路&#xff1a; 私聊写扩散&#xff0c;以用户为中心&#xff0c;存储2次&#xff1b;群聊读扩散&#xff0c;以群组为中心&#xff0c;存储一次&#xff1b;scylladb易于扩展&#xff0c;适合并发&…

蚁剑流量分析

蚁剑流量分析 在靶机上面上传一个一句话木马&#xff0c;并使用蚁剑连接&#xff0c;进行抓包, 一句话木马内容 <?php eval($_POST[1]); defalut编码器 在使用蚁剑连接的时候使用default编码器 连接之后进行的操作行为是查看当前目录(/var/www/html)下的文件&#xff0…

网易云首页单页面html+css

网页设计与网站建设作业htmlcss 预览 源码查看https://hpc.baicaitang.cn/2083.html

书生 浦语 大模型趣味 Demo

目录 一. 部署 InternLM2-Chat-1.8B 模型进行智能对话 1. 环境准备 2. 下载模型参数 3. 运行Demo 二. 部署实战营 八戒-Chat-1.8B 模型 1. 下载Demo仓库 2. 启动web服务端加载八戒模型&#xff1a; 3. 将SSH远程端口映射到本地 4. 在本地浏览器打开&#xff1a;http:/…

【C++第二阶段】案例-职工管理系统

以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 案例>职工管理系统0.退出功能1.增加职工功能2.显示职工信息3.删除职工信息4.修改职工信息5.查找职工信息6.排序职工7.清空所有文档 案例>职工管理系统 首先写一个workmanager…

Adobe ColdFusion 任意文件读取漏洞复现(CVE-2024-20767)

0x01 产品简介 Adobe ColdFusion是美国奥多比(Adobe)公司的一套快速应用程序开发平台。该平台包括集成开发环境和脚本语言,将可扩展、改变游戏规则且可靠的产品的愿景变为现实。 0x02 漏洞概述 由于 Adobe ColdFusion 的访问控制不当,未经身份认证的远程攻击者可以构造恶…

夜晚兼职好选择:六大副业助你增收

晚上兼职&#xff0c;无疑是许多寻求额外收入人群的理想选择。以下为您精心推荐的六个副业&#xff0c;既适合晚间操作&#xff0c;又能让您在轻松愉悦中赚取额外收益。 网络调查与市场研究&#xff1a;利用晚上的闲暇时光&#xff0c;参与网络调查与市场研究&#xff0c;为企业…

《QT实用小工具·七》CPU内存显示控件

1、概述 源码放在文章末尾 CPU内存显示控件 项目包含的功能如下&#xff1a; 实时显示当前CPU占用率。实时显示内存使用情况。包括共多少内存、已使用多少内存。全平台通用&#xff0c;包括windows、linux、ARM。发出信号通知占用率和内存使用情况等&#xff0c;以便自行显示…

思腾合力与中科创达联合推出的迅思代码生成一体机产品

思腾合力与中科创达联合推出的迅思代码生成一体机产品&#xff0c;基于思腾合力强大算力底座&#xff0c;搭载中科创达自研国产大模型&#xff0c;面向众多有编程开发需求的客户&#xff0c;简化编程和软件开发过程 &#xff0c;降低编程门槛&#xff0c;全方位提升开发和生产效…

群晖NAS使用Docker部署大语言模型Llama 2结合内网穿透实现公网访问本地GPT聊天服务

文章目录 1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&#xff0c;包括聊天机…

ssm018简易版营业厅宽带系统+jsp

营业厅宽带系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本营业厅宽带系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间…

【饿了么笔试题汇总】-2024-04-02-饿了么春招笔试题-三语言题解(CPP/Python/Java)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新饿了么近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x…

整型之韵,数之舞:大小端与浮点数的内存之旅

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱’博客 所属栏目&#xff1a;人工智能 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 1.0 整形提升 我们先来看看代码。 int main() {char a 3;char b 127;char …

枚举---算法

1、定义 枚举算法&#xff1a;也称之为穷举算法&#xff0c;这种算法就是在解决问题的时候去使用所有的方式去解决这个问题&#xff0c;会通过推理去考虑事件发生的每一种可能&#xff0c;最后推导出结果。优点&#xff1a;简单粗暴&#xff0c;它暴力的枚举所有可能&#xff…

算法学习——LeetCode力扣图论篇1(797. 所有可能的路径、200. 岛屿数量、695. 岛屿的最大面积)

算法学习——LeetCode力扣图论篇1 797. 所有可能的路径 797. 所有可能的路径 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特…

STM32 DWT数据观察触发器作为延时函数的使用

STM32 DWT数据观察触发器作为延时函数的使用 &#x1f4d1;DWT(Data Watchpoint and Trace数据观察触发器&#xff09;描述 &#x1f4dd;DWT是属于处理器内核单元中的调试组件之一&#xff0c;由四个比较器组成。它们可配置为&#xff1a;硬件监视点或对ETM或PC采样器或数据地…

Ubuntu20.04安装MatlabR2018a

一、安装包 安装包下载链接 提取码&#xff1a;kve2 网上相关教程很多&#xff0c;此处仅作为安装软件记录&#xff0c;方便后续软件重装&#xff0c;大家按需取用。 二、安装 1. 相关文件一览 下载并解压文件后&#xff0c;如下图所示&#xff1a; 2. 挂载镜像并安装 2…

06 | Swoole 源码分析之 Coroutine 协程模块

首发原文链接&#xff1a;Swoole 源码分析之 Coroutine 协程模块 大家好&#xff0c;我是码农先森。 引言 协程又称轻量级线程&#xff0c;但与线程不同的是&#xff1b;协程是用户级线程&#xff0c;不需要操作系统参与。由用户显式控制&#xff0c;可以在需要的时候挂起、或…