spring 详解四 IOC(spring Bean生命周期)

news2024/9/29 23:30:26

spring生命周期概述

spring Bean的生命周期是从Bean实例化之后,即通过反射创建对象之后,到Bean成为一个完整对象,最终存储在单例池中,然后在销毁的过程被称为spring Bean的生命周期,这部分不会介绍销毁过程,只要在从无到有的创建过程

Bean的实例化阶段:spring框架会从BeanDefinitionMap中取出BeanDefinition定义信息判断当前Bean的范围是否是singleton,是否是延迟加载,是否是工厂方法实例化等,最终通过反射创建出Bean对象

Bean的初始化阶段:Bean创建之后仅仅只是个半成品,还需要对Bean进行DI,也就是popluate属性填充,执行一些Aware接口方法,执行BeanPostProcessor#before方法,执行InitializingBean接口初始化方法,执行自定义初始化方法,BeanPostProcessor#after方法执行,该阶段是spring的重要阶段,Aop功能的实现,注解功能,循环依赖功能均在此阶段

Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的sping Bean,被存储到单例池singletonObjects中去了,到此为止,即完成了springBean的整个生命周期

 spirng生命周期图

spring属性填充和三级缓存解决循环依赖 

属性填充位置

BeanDefinition中有对当前Bean实体的注入信息通过属性propertyValues进行存储注入

 属性注入规则

普通属性注入时,String,int或者存储基本类型的集合时,直接通过set方法的反射注入

注入单项对象引用属性时,先从容器中getBean获取后在通过set方法反射设置进去,如果容器中没有,则先创建对象Bean实例,在注入操作

注入双向对象引用属性时,即涉及到了循环引用问题(解决方案是三级缓存)

spring循环依赖问题 

当两个对象互相引用对方对象的时候,就出现了循环引用问题,下面造一个循环引用的问题

package com.tech.test.testbean;

import com.tech.test.service.UserService;


public class DI {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
package com.tech.test.service.impl;

import com.tech.test.service.UserService;
import com.tech.test.testbean.DI;

public class UserServiceImpl implements UserService {


    private DI di;

    public void setDi(DI di) {
        this.di = di;
    }

    @Override
    public void getUser() {
        System.out.println("get User Success");
    }


}
  <bean id="userService"  name="aaa,bbb"  class="com.tech.test.service.impl.UserServiceImpl" >
        <property name="di" ref="di"></property>
    </bean>


    <bean id="di"  class="com.tech.test.testbean.DI" autowire="byName">
        <property name="userService" ref="userService"></property>
    </bean>

 在上边定义的循环引用问题是 userService对象引用了di对象,di对象又引用了userService对象,出现了循环引用问题,也就是死循环

 解决循环依赖问题(三级缓存)

 spring解决循环依赖问题引入了三级缓存

1、实例化对象,没有进行属性注入等初始化操作,会放入三级缓存,这时候的对象是一个半成品,没有被引用

2、当半成品对象被其他对象引用的时候,这个时候将对象放入二级缓存,删除三级缓存,

3、当引用对象的实例化和初始化都完成了进入一级缓存 ,删除二级缓存

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** Cache of singleton objects: bean name to bean instance. */
    // 存储单例Bean成品的容器,一级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of early singleton objects: bean name to bean instance. */
   // 早期的Bean单例池,缓存半成品对象,且对象已经被引用啦,二级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Cache of singleton factories: bean name to ObjectFactory. */
   // 单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean 三级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);



}

上述实例填充步骤:

1、userService实例化对象,分配内存地址,但尚未初始化,将userService存储到三级缓存

2、userService属性注入,需要DI对象,从缓存中取,没有DI对象

3、DI实例化对象,分配内存地址,但尚未初始化,将DI存入三级缓存

4、DI属性注入,需要userService,从三级缓存中取userService,userService从三级缓存中移除,放入二级缓存

5、DI执行初始化,最终成为一个完整的bean,存到一级缓存,移除二级缓存

6、userService 注入DI

7、userService执行初始化等流程,最终形成一个bean,放入一级缓存,移除二三级缓存

 spring中的Aware接口

 Aware接口是一种框架辅助属性注入的一种思想,简单直白的说,就是框架通过Aware接口给我们注入框架底层使用的对象,其他框架也有类似的Aware接口,框架具有高度封装性,底层API不能轻易的获取到,框架通过Aware接口给使用者注入该对象

在属性注入之后执行Aware方法

 常见的Aware接口

Aware接口回调方法作用
ServletContextAwaresetServletContext(ServletContext context)spring框架回调方法注入servletContext对象,web环境生效
BeanFactoryAwaresetBeanFactory(BeanFactory factory)spring框架回调方法注入beanFactory对象
BeanNameAwaresetBeanName(String beanName)spring框架回调方法注入当前Bean在容器中的beanName

ApplicationContextAware

setApplicationContext(ApplicationContext applicationContext)spring回调方法注入applicationContext对象
package com.tech.test.service.impl;

import com.tech.test.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class UserServiceImpl implements UserService, ApplicationContextAware, BeanNameAware {


    @Override
    public void getUser() {
        System.out.println("get User Success");
    }


    @Override
    public void setBeanName(String name) {
        System.out.println(name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(applicationContext);
    }
}

 可以看到 ,spring框架帮我们注入了bean的名称和applicationcontext对象

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

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

相关文章

Spring限流之限流方案分析

文章目录 1 限流方案1.1 引言1.2 常用限流策略1.3 基于guava限流实现1.3.1 引入guava依赖1.3.2 自定义限流注解1.3.3 限流AOP类1.3.4 测试接口 1.4 基于sentinel限流实现1.4.1 引入sentinel核心依赖包1.4.2 自定义限流注解1.4.3 自定义AOP类实现限流1.4.4 自定义测试接口 1.5 基…

独立和相关(线性)的关系

相关(线性)>不独立 不相关(线性) 推不出 独立 (是因为不一定线性相关,可以沿曲线相关)

一起学SF框架系列5.7-模块Beans-BeanDefinition解析

开发人员按元数据规则定义了应用bean&#xff0c;了解SF如何根据定义解析成BeanDefiniton有助于深入理解框架实现。解析过程如下&#xff1a; 资源加载 从资源文件加载bean的元数据配置&#xff0c;实际过程如下图&#xff1a; 实际从指定的XML文件加载bean定义是从XmlBeanD…

电脑pdf如何转换成word格式?分享这三个方法给大家!

记灵在线工具是一个非常方便的PDF转Word工具&#xff0c;它可以帮助用户快速、准确地将PDF文件转换为Word格式。以下是使用步骤&#xff1a; 打开您的网络浏览器&#xff0c;访问记灵在线工具的官方网站。 在首页上找到并点击“PDF转Word”选项。 在新打开的页面中&#xff0…

如何在 SwiftUI 中配置 SwiftData

文章目录 前言创建模型模式和版本控制迈出关键的一步创建迁移计划创建模型容器从视图中查询模型从视图中访问模型上下文总结 前言 在 WWDC 2023 上&#xff0c;Apple 宣布了一个备受期待的新持久性刷新&#xff0c;以一种新的框架形式出现&#xff1a;SwiftData。SwiftData 从…

【设计模式】设计模式前置知识:UML类图入门

UML类图 介绍 UML–Unified modeling language UMl(统一建模语言)&#xff0c;是一种用于软件系统分析和设计的语言工具&#xff0c;它用于帮助软件开发人员进行思考和记录思路的结果UML本身是一套符号的规定&#xff0c;就像数学符号和化学符号一样&#xff0c;这些符号用于…

来啦!OceanBase 第7期技术征文活动获奖名单公布!

“小鱼”的诞生与成长离不开广大开发者的陪伴与支持&#xff0c;我们非常兴奋能把 4.1 版本的这一系列新能力带给大家&#xff0c;“小鱼”会游得更快更远&#xff0c;也会陪伴更多数据库开发者一同成长。 OceanBase 联合墨天轮技术社区&#xff0c;举行「4.1 上手体验」第五届…

基于SpringBoot+Hadoop+Vue的企业网盘系统

完整资料进入【数字空间】查看——baidu搜索"writebug" 1.1.1 选题的背景 随着信息网络技术的迅猛发展&#xff0c;云计算技术从它的概念提出已经开始在实际生产环境中使用了。大部分的东西都已经慢慢云端化&#xff0c;这种新型的技术也受到许多互联网人员的关注&a…

初阶C语言——三子棋

我们今天讲一个小游戏&#xff0c;三子棋大家应该都玩过吧&#xff0c;就是行和列&#xff0c;或者对角线上有一样大的字符时&#xff0c;就为获胜&#xff0c;今天我们就来写这样的一个代码实现这样的功能 首先我们要创建两个源文件和一个头文件 头文件game.h用来包含我们的头…

EmEditor制表符设置为空格

以下是具体操作 工具 - 当前配置属性 - 常规 - 制表符/缩进 - 将制表符转换为空格 前打对钩

作业怎么清除试卷笔迹?拿捏可以擦除答案的方法

在日常学习中&#xff0c;我们经常会遇到需要修改或擦除试卷上的笔迹的情况。本文将介绍一种简单实用的方法&#xff0c;即使用手机拍照扫描试卷并擦除答案。 手机拍照扫描试卷 首先&#xff0c;我们需要使用手机拍照扫描试卷。这一步非常简单&#xff0c;只需要将试卷平铺在桌…

集成学习-BaggingVoting和多个模型的混淆矩阵

当涉及到集成学习时&#xff0c;投票法和袋装法是两种常见的技术&#xff0c;用于将多个基学习器&#xff08;base learner&#xff09;组合成一个强大的集成模型。 投票法&#xff08;Voting&#xff09;&#xff1a;投票法是一种简单且常用的集成学习方法。在投票法中&#…

Django_设置和读取cookie

设置cookie 在响应对象中使用set_cookie方法设置cookie from django.http import HttpResponsedef set_cookie(request):rsp HttpResponse("set cookie")rsp.set_cookie("set_cookie", "hello python", max_age3600)return rsp 注&#xff1…

Latex更改字体颜色以及快速生成 SCI 论文的 revised version 和 pure version

记录一下如何更改 Latex 字体颜色&#xff0c;在返修 SCI 论文时&#xff0c;如何较为快捷地完成 revised version 和 pure version 两个不同版本修改稿件的编辑与生成。 更改字体颜色 导入宏包 在 LaTeX 中&#xff0c;使用 \textcolor 命令或 \color 命令可以改变文本的颜…

十大机器学习算法之一:线性回归

十大机器学习算法之一&#xff1a;线性回归 1 知识预警1.1 线性代数1.2 矩阵微积分 2 什么是回归分析&#xff1f;3 线性回归3.1 一元线性回归3.2 多元线性回归 4 多项式回归 1 知识预警 1.1 线性代数 ( A T ) T A (A^\mathrm{T})^\mathrm{T}A (AT)TA$ ( A B ) T A T B T…

OpenHarmony社区运营报告(2023年6月)

本月快讯 • 6月12日&#xff0c;以“OpenHarmony共建开放&#xff0c;共享未来”为主题的2023开放原子全球开源峰会OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;分论坛在北京北人亦创国际会展中心第一报告厅圆满落幕&#xff0c;根深叶茂&#xff0c…

【Java】面向对象编程 面向对象基础

一、面向对象基础 面向对象编程&#xff0c;是一种通过对象的方式&#xff0c;把现实世界映射到计算机模型的一种编程方法。 现实世界中&#xff0c;我们定义了“人”这种抽象概念&#xff0c;而具体的人则是“小明”、“小红”、“小军”等一个个具体的人。所以&#xff0c;…

uni-app 从零开始第三章:底部 tabBar

pages.json 页面路由 | uni-app官网 一、新建 home页面 找到pages目录&#xff0c;新增一个home的页面&#xff0c;勾选上同时新建文件夹 新建完成后&#xff0c;pages.json 中 会自动添加上刚刚新建的文件信息 二、新增tabBar数据 在 pages.json中新增以下代码 "tabB…

基于pyqt5实现一款简单的界面软件(radioButton、comboBox、pushButton、图片显示)

pyqt5使用记录涉及pyqt界面控件的基本介绍&#xff0c;使用designer设计界面ui&#xff0c;并将其转化为py代码。关于界面主要实现radioButton的互斥选中事件、comboBox的选中事件&#xff08;依据list添加item&#xff09;、pushButton的单击事件、槽函数自动绑定、图片的拖入…

嵌入式开发之上位机工业风界面实现

在做测控类的嵌入式系统开发时&#xff0c;一个精美的上位机控制软件UI是可以为系统增色不少&#xff0c;一般会采用组态软件来开发&#xff0c;我们来看看下面的界面 是不是非常直观有工业质感&#xff0c;还可以根据实时数据进行动态的显示和动画效果&#xff0c;那这些炫酷的…