springBean生命周期解析

news2024/11/15 15:52:38

本文基于Spring5.3.7

参考:
kykangyuky Spring中bean的生命周期
阿斌Java之路 SpringBean的生命周期,
杨开振 JavaEE互联网轻量级框架整合开发
黑马程序员 JavaEE企业级应用开发教程
马士兵 Spring源码讲解

一. SpringBean生命周期流程图

SpringBean生命周期流程

二. 示例代码

1. 定义果汁描述实体类

package com.xiaobai.spring_bean_life_cycle;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @author wangtw
 * @date 2023/6/24 16:38
 * @description 果汁描述实体类
 */
@Slf4j
@Data
public class Source {

    public Source() {
        log.info("source实例化");
    }

    /**
     * 水果
     */
    private String fruit;

    /**
     * 糖量
     */
    private String sugar;

    /**
     * 大小
     */
    private String size;
}

2. 定义果汁生成器

package com.xiaobai.spring_bean_life_cycle;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author wangtw
 * @date 2023/6/24 16:28
 * @description 果汁生成器
 */
@Slf4j
@Data
public class JuiceMaker implements BeanNameAware, BeanFactoryAware,
        ApplicationContextAware, InitializingBean, DisposableBean {

    public JuiceMaker(){
        log.info("juice实例化");
    }

    private String beverageShop;

    private Source source;

    /**
     * 自定义初始化方法
     */
    public void init() {
        log.info("【{}】执行自定义初始化方法", this.getClass().getSimpleName());
    }

    /**
     * 自定义销毁方法
     */
    public void myDestroy() {
        log.info("【{}】执行自定义销毁方法", this.getClass().getSimpleName());
    }

    public String makeJuice() {
        String juice = "这是一杯由" + beverageShop + "饮品店,提供的" + source.getSize() + source.getSugar() + source.getFruit();
        return juice;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("【{}】调用BeanFactoryAware接口的setBeanFactory方法", this.getClass().getSimpleName());
    }

    @Override
    public void setBeanName(String s) {
        log.info("【{}】调用BeanNameAware接口的setBeanName方法", this.getClass().getSimpleName());
    }

    @Override
    public void destroy() throws Exception {
        log.info("调用接口DisposableBean的destroy方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("【{}】调用InitializingBean接口的afterPropertiesSet方法", this.getClass().getSimpleName());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("【{}】调用ApplicationContextAware接口的setApplicationContext方法", this.getClass().getSimpleName());
    }
}

3. 定义Bean实现BeanPostProcessor接口

package com.xiaobai.spring_bean_life_cycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @author wangtw
 * @date 2023/6/24 16:07
 * @description
 */
@Slf4j
public class BeanPostProcessorImpl implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("【{}】对象{}预初始化开始", bean.getClass().getSimpleName(), beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("【{}】对象{}预初始化完成", bean.getClass().getSimpleName(), beanName);
        return bean;
    }
}

4. 定义SpringBean配置类

package com.xiaobai.spring_bean_life_cycle;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author wangtw
 * @date 2023/6/25 10:33
 * @description Spring配置类
 */
@Configuration
public class LifeConfiguration {

    @Bean("beanPostProcessor")
    public BeanPostProcessor beanPostProcessor() {
        return new BeanPostProcessorImpl();
    }

    @Bean("source")
    public Source source() {
        Source source = new Source();
        source.setFruit("橙汁");
        source.setSugar("少糖");
        source.setSize("大杯");
        return source;
    }

    @Bean(value = "juiceMaker", initMethod = "init", destroyMethod = "myDestroy")
    public JuiceMaker juiceMaker() {
        JuiceMaker juiceMaker = new JuiceMaker();
        juiceMaker.setSource(source());
        juiceMaker.setBeverageShop("贡茶");
        return juiceMaker;
    }
}

5. 测试类及输出结果

package com.xiaobai.spring_bean_life_cycle;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author wangtw
 * @date 2023/6/25 10:40
 * @description springBean生命周期测试类
 */
@Slf4j
public class SpringBeanLifeTest {

    @Test
    public void testLifeCycle() {
        ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(LifeConfiguration.class);
        JuiceMaker juiceMaker = (JuiceMaker) context.getBean("juiceMaker");
        log.info(juiceMaker.makeJuice());
        context.close();
    }
}

在这里插入图片描述

三. 源码解析

(一)Bean实例化

1. 根据注解加载Bean

org.springframework.beans.factory.config.BeanFactoryPostProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

2. 在SpringBean实例化前会把扫描到的类加载到BeanDefinition中,然后将BeanDefinition中的信息注册到Spring容器中

org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()
org.springframework.context.annotation.AnnotationConfigApplicationContext#register
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean
org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinition

3. 完成了BeanDefinition注册后,对Bean进行实例化

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

(二)初始化

1. 属性赋值

(1)自定义对象属性赋值

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

(2)容器对象赋值:检查aware接口并设置相关依赖(aware接口用于标记,判断调用什么方法)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

2. 执行前置处理方法

org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization

3. 执行初始化方法

(1)检测Bean是否实现了InitializingBean接口

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

(2)调用afterPropertiesSet方法

org.springframework.beans.factory.InitializingBean#afterPropertiesSet

(3)调用自定义初始化方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeCustomInitMethod

4. 执行后置处理方法

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

创建代理对象
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
org.springframework.aop.framework.AopProxy#getProxy(java.lang.ClassLoader)

(三)使用

(四)销毁

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

升级到mybatis-plus,系统启动的一些问题

在分表后mybatis-plus删除操作失效等问题处理 mybatis-plus 旧系统重构遇到的种种问题 在这三篇文章中&#xff0c;我花了近1个月时间重构了28个微服务&#xff0c;当中遇到的一些问题&#xff0c;但是发布到pretest环境&#xff0c;却还有启动问题&#xff0c;看来系统重构不是…

变压器参数测定中空载实验和短路实验的理解

确定变压器的参数是在《电机学》和《电力系统分析》中非常重要的一个环节&#xff0c;这里用自己习惯的方式讲一下怎样理解 首先要讲下变压器的额定参数&#xff0c;这个也是个常考的知识点 额定功率&#xff0c;即视在功率&#xff0c;电压电流&#xff0c;单位是VA或者kVA额…

【docker】dockerfile发布springboot项目

目录 一、实现步骤二、示例 一、实现步骤 1.定义父镜像&#xff1a;FROM java:8 2.定义作者信息&#xff1a;MAINTAINER&#xff1a;learn_docker<https://www.docker.com> 3.将jar包添加到容器&#xff1a;ADD jar包名称.jar app.jar 4.定义容器启动执行命令&#xff1a…

在tensorflow分布式训练过程中突然终止(终止)

问题 这是为那些将从服务器接收渐变的员工提供的培训功能&#xff0c;在计算权重和偏差后&#xff0c;将更新的渐变发送到服务器。代码如下&#xff1a; def train():"""Train CIFAR-10 for a number of steps."""g1 tf.Graph()with g1.as_de…

不规则文件转JSON

需求分析&#xff1a; 有时候&#xff0c;我们取出来的数据并不是一个规则的JSON文件&#xff0c;这个时候面对存库还是ES检索都是一个问题&#xff0c;所以我们就需要进行解析&#xff0c;然而用字符串分割是不现实的&#xff0c;我们需要一种快速的方法。 问题解决&#x…

设计模式行为型——备忘录模式

目录 什么是备忘录模式 备忘录模式的实现 备忘录模式角色 备忘录模式类图 备忘录模式举例 备忘录模式代码实现 备忘录模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是备忘录模式 备忘录模式&#xff08;Memento Pattern&#xff09;又叫做快照模式&#x…

ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts

ant.design 组件库中的 Tree 组件实现可搜索的树&#xff0c;在这里我会详细介绍每个方法&#xff0c;以及容易踩坑的点。 效果图&#xff1a; 首先是要导入的文件 // React 自带的属性 import React, { useMemo, useState } from react; // antd 组件库中的&#xff0c;输入…

VSCode插件Todo Tree的使用

在VSCode中安装插件Todo Tree。按下快捷键ctrlshiftP&#xff0c;输入setting.jspn&#xff0c;选择相应的配置范围&#xff0c;我们选择的是用户配置 Open User Settings(JSON)&#xff0c;将以下代码插入其中。 //todo-tree 标签配置从这里开始 标签兼容大小写字母(很好的功…

JAVA方向的大数据包含啥内容?

文章目录 大数据是啥大数据就业方向知识体系HadoophiveHBaseSparkScala 总结 大数据是啥 你了解到的大数据是啥样子&#xff1f; 还是… 大数据(big data)&#xff0c;或称巨量资料&#xff0c;指的是所涉及的资料量规模巨大到无法透过主流软件工具&#xff0c;在合理时间…

麦肯锡战略思维四大原则

麦肯锡战略思维四大原则 曾任职麦肯锡、安永等国家国际知名咨询机构的周正元&#xff0c;在其著作《麦肯锡结构化战略思维》将其系统的整理呈现出来&#xff0c;便于学习和使用。 模型介绍 工作中的你&#xff0c;是不是经常遇到复杂问题&#xff0c;六神无主&#xff1f; 专业…

SpringBoot+SSM实战<一>:打造高效便捷的企业级Java外卖订购系统

文章目录 项目简介项目架构功能模块管理端用户端 技术选型用户层网关层应用层数据层工具 项目优缺点结语 黑马程序员最新Java项目实战《苍穹外卖》&#xff1a;让你轻松掌握SpringBootSSM的企业级开发技巧项目简介 《苍穹外卖》是一款为餐饮企业&#xff08;餐厅、饭店&#x…

PBR材质理解整理

PBR Material 草履虫都能看懂的PBR讲解&#xff08;迫真&#xff09; 先前看了很多遍类似的了&#xff0c;结合《Unity Shader 入门精要》中的内容整理了下便于以后理解&#xff0c;以后有补充再添加。 光与材质相交会发生散射和吸收&#xff0c;散射改变光的方向&#xff0c…

MySQL主从复制——概念、原理、搭建过程

文章目录 1.主从复制概念2.主从复制原理3.主从复制结构的搭建3.1 主库配置3.2 从库配置 4.测试主从复制是否搭建成功5.主从复制的小结 DML&#xff08;data manipulation language&#xff09;是数据操纵语言&#xff1a;它们是SELECT、UPDATE、INSERT、DELETE&#xff0c;就象…

LeetCode 热题 100 JavaScript--108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 提示&#xff1a; 1 < nums.length < 104 -104 < n…

怎么维护好自己的电脑

你的电脑已经成为你工作、学习、娱乐的最佳工具之一&#xff0c;但是如果你不做好电脑维护工作&#xff0c;就可能面临着电脑变慢、蓝屏、崩溃等问题。在这篇文章中&#xff0c;我们将介绍10个电脑维护步骤&#xff0c;让你的电脑更加稳定&#xff01; 为什么需要电脑维护&…

【Kubernetes部署篇】基于Ubuntu20.04操作系统搭建K8S1.23版本集群

文章目录 一、集群架构规划信息二、系统初始化准备(所有节点同步操作)三、安装kubeadm(所有节点同步操作)四、初始化K8S集群(master节点操作)五、添加Node节点到K8S集群中六、安装Calico网络插件七、测试CoreDNS可用性 一、集群架构规划信息 pod网段&#xff1a;10.244.0.0/16…

我的创作纪念日-三周年

机缘 工作很长时间之后&#xff0c;才发现知识的根本&#xff0c;还是在于积累。俗话说好记性不如烂笔头。不管是特定产品相关的知识还是系统类的知识&#xff0c;又或者是语言类的知识&#xff0c;都有很多知识点需要积累。有了积累之后&#xff0c;工作起来才游刃有余。 原来…

掌握Memory Profiler技巧:识别内存问题

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、如何使用四、页面说明4.1 Java 和 Kotlin 分配…

snap xxx has “install-snap“ change in progress

error description * 系重复安装&#xff0c;进程冲突 solution 展示snap的改变 然后sudo snap abort 22即可终止该进程 之后重新运行install command&#xff5e;&#xff5e; PS: ubuntu有时候加载不出来&#xff0c;执行resolvectl flush-caches&#xff0c;清除dns缓存…

Red Hat 安装JDK与IntelliJ IDEA

目录 前言 Red Hat 安装 JDK 1、更新软件包列表 2、安装OpenJDK 3、验证安装 Red Hat 安装IntelliJ IDEA 1、下载 IntelliJ IDEA 2、解压缩 IntelliJ IDEA 安装包 3、移动 IntelliJ IDEA 到安装目录 4、启动 IntelliJ IDEA 前言 YUM是基于Red Hat的Linux发行版的一个…