spring框架4 - bean加载

news2024/11/14 14:21:42

本节内容:beanFactory.getBean("user");

    @Test
    void testGetBean() {
        Gun gun = beanFactory.getBean("m416", Gun.class);
        log.info("gun={}", gun);
    }
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	return this.doGetBean(name, requiredType, (Object[])null, false);
}
	/**
	 * 返回指定bean的一个实例,该实例可以是共享的,也可以是独立的
	 */
	// eg1:name="m416",requiredType=Gun.class,args=null,typeCheckOnly=false
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		// 提取真正的beanName(去除‘&’或者将别名name转化为beanName)
		String beanName = transformedBeanName(name); // eg1:beanName="m416"

		/** 1:尝试根据beanName,从缓存中获得单例对象 */
		Object beanInstance, sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null)  // eg1:sharedInstance=null
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); // 从bean中获得真正的实例对象

		/** 2:缓存中不存在实例,则采取自主创建实例对象 */
		else {
			// 如果当前bean是正在创建中的原型对象,则直接抛出异常
			if (isPrototypeCurrentlyInCreation(beanName)) // eg1:false
				throw new BeanCurrentlyInCreationException(beanName);

			/** 3:如果存在parentBeanFactory 并且 配置中也没有beanName的配置信息,则尝试从parentBeanFactory中获取实例 */
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // eg1:parentBeanFactory=null
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory)
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
				else if (args != null)
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				else if (requiredType != null)
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				else
					return (T) parentBeanFactory.getBean(nameToLookup);
			}

			// 如果不执行类型检查,则将beanName保存到alreadyCreated缓存中
			if (!typeCheckOnly) // eg1:true
				markBeanAsCreated(beanName);

			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
			try {
				if (requiredType != null) // eg1:requiredType=Gun.class
					beanCreation.tag("beanType", requiredType::toString);

				/** 4:将GenericBeanDefinition转换为RootBeanDefinition,如果是子Bean,则与父类的相关属性进行合并 */
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args); // eg1:mbd=RootBeanDefinition@2607

				/** 5:如果存在依赖,那么需要递归每一个依赖的bean并对其进行实例化创建 */
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) { // eg1:dependsOn=null
					for (String dep : dependsOn) {
						// 如果发生了循环依赖,则直接抛出异常
						if (isDependent(beanName, dep))
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");

						registerDependentBean(dep, beanName);
						try {
							getBean(dep); // 创建每一个依赖(dep)的实例Bean
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				/** 6:创建bean的单例实例对象 */
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args); // eg1:return Gun@2334
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					// eg1:AbstractAutowireCapableBeanFactory#getObjectForBeanInstance
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				/** 7:创建原型对象 */
				else if (mbd.isPrototype()) {
					Object prototypeInstance;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				/** 8:创建指定scope类型的对象 */
				else {
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName))
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");

					Scope scope = this.scopes.get(scopeName);
					if (scope == null)
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");

					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end(); // eg1:DefaultApplicationStartup#end()
			}
		}

		/** 9:检查需要的类型是否符合bean的实际类型,如果不同,则对其进行类型转换 */
		return adaptBeanInstance(name, beanInstance, requiredType); // eg1:return Gun@2334
	}

// 提取真正的beanName(去除‘&’或者将别名name转化为beanName)

// 提取真正的beanName(去除‘&’或者将别名name转化为beanName)
String beanName = transformedBeanName(name); // eg1:beanName="m416"
/**
 * 返回bean名称,必要时去掉工厂引用前缀,并将别名解析为规范名称
 */
// eg1:name="m416"
protected String transformedBeanName(String name) {
	return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
/**
 * 返回实际的bean名称,去掉工厂解引用前缀(如果有,也去掉重复的工厂前缀)
 */
// eg1:name="m416"
public static String transformedBeanName(String name) {
	Assert.notNull(name, "'name' must not be null");

	// 如果不是"&"前缀,则直接返回name即可
	if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) // eg1:true
		return name; // eg1:return "m416"

	// 去掉所有前缀"&",只返回beanName
	return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
		do {
			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		}
		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
		return beanName;
	});
}
/**
 * 确定原始名称,将别名解析为规范名称
 */
// eg1:name="m416"
public String canonicalName(String name) {
	String canonicalName = name;
	String resolvedName;
	do {
		// eg1:result = {ConcurrentHashMap@2355}  size = 5
		// 			"com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor" -> "com.muse.springdemo.beanpostprocessor.MuseBeanPostProcessor#0"
		// 			"org.springframework.web.servlet.view.InternalResourceViewResolver" -> "org.springframework.web.servlet.view.InternalResourceViewResolver#0"
		// 			"muse" -> "customUser"
		// 			"alias_ent" -> "ent"
		// 			"org.springframework.beans.factory.config.CustomEditorConfigurer" -> "org.springframework.beans.factory.config.CustomEditorConfigurer#0"
		/** 从别名中寻找原始名称 */
		resolvedName = this.aliasMap.get(canonicalName);
		if (resolvedName != null) // eg1:resolvedName=null
			canonicalName = resolvedName;
	}
	while (resolvedName != null);
	return canonicalName; // eg1:return "m416"
}

 


/** 1:尝试根据beanName,从缓存中获得单例对象 */
/** 2:缓存中不存在实例,则采取自主创建实例对象 */
    // 如果当前bean是正在创建中的原型对象,则直接抛出异常
    /** 3:如果存在parentBeanFactory 并且 配置中也没有beanName的配置信息,则尝试从parentBeanFactory中获取实例 */
    // 如果不执行类型检查,则将beanName保存到alreadyCreated缓存中
        /** 4:将GenericBeanDefinition转换为RootBeanDefinition,如果是子Bean,则与父类的相关属性进行合并 */
        /** 5:如果存在依赖,那么需要递归每一个依赖的bean并对其进行实例化创建 */
                // 如果发生了循环依赖,则直接抛出异常
        /** 6:创建bean的单例实例对象 */
        /** 7:创建原型对象 */
        /** 8:创建指定scope类型的对象 */
/** 9:检查需要的类型是否符合bean的实际类型,如果不同,则对其进行类型转换 */
 

 

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

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

相关文章

2024年威胁暴露管理两大新趋势

文章目录 前言一、威胁暴露管理的两大新类别二、EAP:减少对CVSS的依赖三、AEV:锁定现实威胁四、CTEM实施面临的挑战与应对策略五、主动风险管理的新时代前言 2024年,安全运营(SecOps)领域迎来重大变革。根据Gartner最新发布的《安全运营技术成熟度曲线》报告,持续威胁暴…

一款人脸识别的芯片内部

三年前在一家3D人脸识别的芯片公司&#xff0c;先后做过两个稍具规模的芯片项目&#xff0c;因为各种原因&#xff0c;这些最终都没有上市&#xff0c;成为沉寂在实验室的产物。但是这些芯片的总体设计都颇具匠心&#xff0c;自己在当时也很有触动&#xff0c;现在拿出一点来供…

揭秘难以复现Bug的解决之道:堆栈分析实战

目录 引言 友情提示难以复现的Bug之痛 寄存器(SP、LR)详解 SP寄存器&#xff1a;堆栈的指路明灯LR寄存器&#xff1a;函数调用与异常处理的桥梁 问题分析与解决流程揭秘 保存现场分析堆栈数据 堆栈结构入栈顺序 案例 J-Link工具 常用命令保存RAM数据到本地 分析栈基本信息 分…

【最新华为OD机试E卷】最大报酬(100分)-多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,…

【Python】企业排名、地域分布与词云分析可视化

目录 数据处理 Pyecharts 各国数量 分布地图 数量占比 城市分布 营业收入 利润转化 数据处理 2021世界五百强企业数据&#xff0c;包含公司名称、公司链接、营业收入(百万美元)、利润(百万美元)、国家等信息。数据集下载&#xff1a;Python企业排名、地域分布与词云分…

opencv-python 图像增强十七:泊松图像融合

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、概述二&#xff0c;实现&#xff1a; 前言 在深入探讨图像处理与计算机视觉领域的过程中&#xff0c;我们不禁对图像融合技术的精妙与实用性感到着迷。图像…

物联网之云平台架构

一&#xff0c;一个典型的物联网云平台 一个典型的物联网&#xff08;IoT&#xff09;云平台需要实现多个功能&#xff0c;以支持物联网设备的接入、数据处理、设备管理、实时控制等需求。 &#xff08;一&#xff09;核心功能 1&#xff0c;设备接入与管理&#xff1a; - 设…

【达梦数据库】DBeaver连接达梦数据库

打开 DBeaver&#xff0c;新建驱动管理器 新建驱动管理器&#xff0c;配置信息如下 添加库文件&#xff0c;jar包使用项目上使用的jdbc驱动包即可&#xff0c;找到本地maven仓库jar位置进行添加。 <dependency><groupId>com.dameng</groupId><artifact…

打开配置好的gee的jupyter Lab环境

目录 打开anconda 打开箭头下的cmd环境&#xff0c;输入jupyter lab

Spring MVC 八股文

目录 重点 SpringMVC的工作原理 Spring MVC 拦截器 Spring MVC 的拦截器和 Filter 过滤器有什么差别&#xff1f; 基础 什么是SpringMVC SpringMVC的优点 Spring MVC的核心组件 Spring MVC的常用注解由有哪些 Controller 注解有什么用 重点 SpringMVC的工作原理 1、客…

人脸静态活体检测(高精度版) API 对接说明

人脸静态活体检测&#xff08;高精度版&#xff09; API 对接说明 本文将介绍人脸静态活体检测&#xff08;高精度版&#xff09;API 对接说明&#xff0c;它可用于对用户上传的静态图片进行防翻拍活体检测&#xff0c;以判断是否是翻拍图片。 接下来介绍下 人脸静态活体检测…

浅谈sizeof() 函数在Arduino中的使用

下面浅谈 sizeof() 函数在Arduino中的使用 注意&#xff1a;这里用sizeof(str[2])&#xff0c;sizeof(str[0])&#xff0c;sizeof(str[1])都是一样的 String str[6]{"abc","defg","hijk","lm","n"}; int num; void setup…

C++项目详细分析_WebServer

前言 项目地址 项目介绍 源码详细分析 项目路径如下&#xff1a; 1.webserver.cpp 头文件和构造函数 #include "webserver.h"WebServer::WebServer() {// http_conn类对象users new http_conn[MAX_FD];// root文件夹路径char server_path[200];getcwd(server…

【C++】N卡无法录制,如何下载C++

N卡无法录制&#xff0c;如何下载C C 官方下载路径&#xff1a; https://www.microsoft.com/zh-cn/download/details.aspx?id48145&134b2bb0-86c1-fe9f-d523-281faef416951&751be11f-ede8-5a0c-058c-2ee190a24fa6True 第一步 检查N卡驱动是不是最新版本 第二步 下载…

拓扑结构_替代SN6505推挽式低噪声隔离变压驱动器输出功率1-3W

PC6505 是一款专门为小体积、低待机功耗微功率隔离电源而设计的推挽式变压器驱动器&#xff0c;其外围只需匹配简单的输入输出滤波电容、隔离变压器和整流电路&#xff0c;即可实现 3.3V 或 5V 输入、3.3V~24V 输出、输出功率 1~3W 的隔离电源。 PC6505 芯片内部集成振荡器&am…

简单的棒棒图绘制教程

原文教程链接&#xff1a;R 语言绘图 | GO、KEGG等富集棒棒图 往期部分文章 1. 最全WGCNA教程&#xff08;替换数据即可出全部结果与图形&#xff09; WGCNA分析 | 全流程分析代码 | 代码一 WGCNA分析 | 全流程分析代码 | 代码二 WGCNA分析 | 全流程代码分享 | 代码三 WGC…

stun和trun

在 WebRTC 中&#xff0c;STUN&#xff08;Session Traversal Utilities for NAT&#xff09;和 TURN&#xff08;Traversal Using Relays around NAT&#xff09;是用于NAT穿透的两种不同的技术&#xff0c;它们解决的问题不同&#xff0c;因此在某些情况下需要同时使用。 ST…

VM虚拟机:虚拟机能ping通主机,主机ping不通虚拟机,永久解决办法。

最近在安装VM虚拟机的时候,出现了虚拟机能ping通主机,主机ping不通虚拟机。着实令人恶心,尤其是虚拟机在设置网络的时候,网上五花八门,修改什么配置的都有,最多的就是修改宿主机的ipv4,这种我个人感觉不可取。宿主机不要乱改配置,需要修改尽量在虚拟机中修改即可。 还需…

el-time-select 动态增加时间

<template><div><div v-for"(item, index) in timeSlots" :key"index"><el-time-select placeholder"起始时间" v-model"item.startTime" :picker-options"{start: 00:00,step: 00:15,end: 23:59,}"&g…

VMware安装windows虚拟机详细过程

目录 准备工作配置虚拟机为虚拟机设置操作系统镜像安装windows10 准备工作 安装好VMware软件并激活&#xff0c;激活码自行查找 准备好系统镜像文件&#xff0c;可以在MSDN中下载&#xff0c;地址&#xff1a;https://next.itellyou.cn/ 配置虚拟机 选择自定义 默认 选择稍后…