spring框架4 - bean加载

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

java 复制代码
    @Test
    void testGetBean() {
        Gun gun = beanFactory.getBean("m416", Gun.class);
        log.info("gun={}", gun);
    }
java 复制代码
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	return this.doGetBean(name, requiredType, (Object[])null, false);
}
java 复制代码
	/**
	 * 返回指定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)

java 复制代码
// 提取真正的beanName(去除'&'或者将别名name转化为beanName)
String beanName = transformedBeanName(name); // eg1:beanName="m416"
java 复制代码
/**
 * 返回bean名称,必要时去掉工厂引用前缀,并将别名解析为规范名称
 */
// eg1:name="m416"
protected String transformedBeanName(String name) {
	return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
java 复制代码
/**
 * 返回实际的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;
	});
}
java 复制代码
/**
 * 确定原始名称,将别名解析为规范名称
 */
// 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的实际类型,如果不同,则对其进行类型转换 */

相关推荐
宸津-代码粉碎机3 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
噢,我明白了5 小时前
java中唯一键和幂等键的应用
java·后端
程序猿乐锅5 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
福兮说5 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
GreenTea5 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
考虑考虑5 小时前
synchronized字符串常量
java·后端·java ee
长谷深风1115 小时前
Tool与Skill:AI能力设计的分水岭
java·人工智能·ai·大模型·aiagent
科技观察哨5 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
m0_587383005 小时前
广州24小时自助健身房解决方案实战指南与系统部署要点
java·spring·小程序·架构·需求分析
Escalating_xu5 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言