老生谈spring(十八):getBean

本文详细介绍了Spring的getBean方法的工作原理,包括从三级缓存中获取Bean,检查父容器,处理依赖关系以及针对不同作用域(单例、多例、自定义)的Bean创建流程。此外,还预告了后续将要讨论的Spring循环依赖问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

老生谈spring(十八):getBean

1、preInstantiateSingletons这个方法会遍历beanNames时首先判断这个bean是不是FactoryBean,如果是则创建FactoryBean,否则直接getBean创建这个bean。这个方法在容器初始化的时候被调用,至于单例的非懒加载的bean才会被创建。

在这里插入图片描述2、getBean调用了doGetBean方法,看了这么久的spring代码,想必你已经指定带do的方法才是真正干活的。(doGetBean方法稍长,将拆分成几段)
在这里插入图片描述

3、doGetBean方法一进来就从三级缓存中取,这个三级缓存是用来解决spring的循环依赖的,后面的章节会详细讲解。由于一开始这个bean是没有创建,所有肯定获取不到,所有第一个if条件是不成立。
在这里插入图片描述4、if条件不成立就会进入else,这一段代码就是看这个容器有没有父容器,如果有则调用父容器的getBean方法创建Bean。举个例子,例如项目中引用了spring和springMVC的web容器,SpringMVC就是子容器,spring就是父容器。这个在将springMVC的时候细讲。
在这里插入图片描述5、如果没有父容器,就用这个容器创建bean。创建时先检查这个bean有没有dependsOn属性,如果有则优先创建dependsOn指定的bean。
在这里插入图片描述6、检查完dependsOn就判断这个bean的作用域,这里的作用域有三种:单例、多例以及自定义的作用域。不同的作用域创建bean的流程是不一样的,所有后面会分开细讲。

				// 单例域
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				//多例域
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				//自定义作用域
				else {
					String scopeName = mbd.getScope();
					final 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);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

7、结语:本节主要展示了doGetBean方法主要干的事情,下一节将围绕单例域展开spring循环依赖的讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值