springBean生命周期解析

本文基于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)

(三)使用

(四)销毁

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

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

相关文章

第 357 场力扣周赛题解

A 故障键盘 简单模拟 class Solution { public:string finalString(string s) {string res;for (auto c: s)if (c ! i)res.push_back(c);elsereverse(res.begin(), res.end());return res;} };B 判断是否能拆分数组 区间dp&#xff1a;定义 p i , j p_{i,j} pi,j​表示子数组 n…

R语言3_安装SeurateData

环境Ubuntu22/20, R4.1 在命令行中键入&#xff0c; apt-get update apt install libcurl4-openssl-dev libssl-dev libxml2-dev libcairo2-dev libgtk-3-dev # libcairo2-dev :: systemfonts # libgtk :: textshaping进入r语言交互环境&#xff0c;键入&#xff0c; instal…

基于二进制草蝉优化算法选择特征并使用 KNN 进行训练(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 基于二进制草蝉优化算法选择特征并使用KNN&#xff08;K-Nearest Neighbors&#xff0c;K最近邻算法&#xff09;进行训练是一种…

安全基础 --- https详解 + 数组(js)

CIA三属性&#xff1a;完整性&#xff08;Confidentiality&#xff09;、保密性&#xff08;Integrity&#xff09;、可用性&#xff08;Availability&#xff09;&#xff0c;也称信息安全三要素。 https 核心技术&#xff1a;用非对称加密传输对称加密的密钥&#xff0c;然后…

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离 (三)

本篇主要说明&#xff1a; 1. 因为这个mysql版本是8.0&#xff0c;所以当其中一台mysql节点挂掉之后&#xff0c;主从同步&#xff0c;甚至双向数据同步都失效了&#xff0c;所以本篇主要记录下当其中的节点挂掉之后如何再次生效。另外推荐大家使用mysql5.7的版本&#xff0c;这…

ORA-12154:TNS:could not resolve the connect identifier specified

避免中文乱码 NLS_LANG: AMERICAN_AMERICA.UTF8 tnsnames.ora 所在目录 TNS_ADMIN: F:\Program\instantclient_11_2\NETWORK\ADMIN

MacBook触控板窗口管理 Swish for Mac

Swish for Mac是一款用于通过手势来控制mac应用窗口的软件&#xff0c;你可以通过这款软件在触控板上进行手势控制&#xff0c;你可以在使用前预设好不同手势的功能&#xff0c;然后就能直接通过这些手势让窗口按照你想要的方式进行变动了 Swish 支持 Haptick Feedback 震动反…

postgresql|数据库|MySQL数据库向postgresql数据库迁移的工具pgloader的部署和初步使用

前言&#xff1a; MySQL数据库和postgresql数据库之间的差异并不多&#xff0c;这里的差异指的是对SQL语言的支持两者并不大&#xff0c;但底层的东西差异是非常多的&#xff0c;例如&#xff0c;MySQL的innodb引擎概念&#xff0c;数据库用户管理&#xff0c;这些和postgresq…

ruby调试

如果下载 ruby-debug-ide gem install ruby-debug-ide vscode 下载 ruby扩展 1&#xff0c; ruby 2&#xff0c;修改launch.json

windows .gitignore 加入文件名后 依然可以从git status中看到文件问题

最近在学git&#xff0c;对着b站的视频操作&#xff0c;结果很简单的添加.gitignore文件操作&#xff0c;up主的正常隐藏&#xff0c;我的却一直出问题。 百思不得其解&#xff0c;网上各种啥啥啥清缓存都没讲到点上。 最后发现是.gitignore文件有问题&#xff0c;windows默认…

LNMP及论坛搭建

安装 Nginx 服务 systemctl stop firewalld systemctl disable firewalld setenforce 0 1.安装依赖包 #nginx的配置及运行需要pcre、zlib等软件包的支持&#xff0c;因此需要安装这些软件的开发包&#xff0c;以便提供相应的库和头文件。 yum -y install pcre-devel zlib-devel…

Linux【网络编程】之深入理解TCP协议

Linux【网络编程】之深入理解TCP协议 TCP协议TCP协议段格式4位首部长度---TCP报头长度信息 TCP可靠性&#xff08;确认应答&#xff09;&& 提高传输效率确认应答(ACK)机制32位序号与32为确认序号 16位窗口大小---自己接收缓冲区剩余空间的大小16位紧急指针---紧急数据处…

Vue电商项目--订单和支付

提交订单 没有组件&#xff0c;先搬组件 配置路由 然后静态pay页面就有了 这里提交订单不是简单的直接进行路由的跳转&#xff0c;而且要拿你支付的数据向服务器发请求 提交订单 请求地址 /api/order/auth/submitOrder?tradeNo{tradeNo} 请求方式 POST 参数类型 参数名…

边写代码边学习之LSTM

1. 什么是LSTM 长短期记忆网络 LSTM&#xff08;long short-term memory&#xff09;是 RNN 的一种变体&#xff0c;其核心概念在于细胞状态以及“门”结构。细胞状态相当于信息传输的路径&#xff0c;让信息能在序列连中传递下去。你可以将其看作网络的“记忆”。理论上讲&a…

Stable Diffusion - Candy Land (糖果世界) LoRA 提示词配置与效果展示

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132145248 糖果世界 (Candy Land) 是一个充满甜蜜和奇幻的地方&#xff0c;由各种各样的糖果和巧克力构成。在糖果世界&#xff0c;可以看到&…

Qt、C/C++环境中内嵌LUA脚本、实现LUA函数的调用执行

Qt、C/C环境中内嵌LUA脚本、实现LUA函数的调用执行 Chapter1. Qt、C/C环境中内嵌LUA脚本、实现LUA函数的调用执行1、LUA简介2、LUA脚本的解释器和编译器3、C环境中内嵌LUA执行LUA函数调用4、Qt内嵌LUA执行LUA函数调用5、运行结果6、内嵌LUA脚本在实际项目中的案例应用 Chapter1…

手机变电脑2023之虚拟电脑droidvm

手机这么大的内存&#xff0c;装个app来模拟linux&#xff0c;还是没问题的。 app 装好后&#xff0c;手指点几下确定按钮&#xff0c;等几分钟就能把linux桌面环境安装好。 不需要敲指令&#xff0c; 不需要对手机刷机&#xff0c; 不需要特殊权限&#xff0c; 不需要找驱…

opencv-32 图像平滑处理-高斯滤波cv2.GaussianBlur()

在进行均值滤波和方框滤波时&#xff0c;其邻域内每个像素的权重是相等的。在高斯滤波中&#xff0c;会将中心点的权重值加大&#xff0c;远离中心点的权重值减小&#xff0c;在此基础上计算邻域内各个像素值不同权重 的和。 基本原理 在高斯滤波中&#xff0c;卷积核中的值不…

第一篇:一文看懂 Vue.js 3.0 的优化

我们的课程是要解读 Vue.js 框架的源码&#xff0c;所以在进入课程之前我们先来了解一下 Vue.js 框架演进的过程&#xff0c;也就是 Vue.js 3.0 主要做了哪些优化。 Vue.js 从 1.x 到 2.0 版本&#xff0c;最大的升级就是引入了虚拟 DOM 的概念&#xff0c;它为后续做服务端渲…

Scala按天写入日志文件

如果希望把每天出错的信息写入日志文件&#xff0c;每天新建一个文件。 package test.scala import java.io.{File, FileWriter} import java.text.SimpleDateFormat import java.util.{Calendar, Date} import scala.concurrent.ExecutionContext.Implicits.global import sc…