Spring获取Bean的过程探索

        上一篇Spring创建Bean我们知道了,Spring创建Bean后,会将Bean存放在容器的singletonObjects中,那么获取一个bean的过程又是如何呢?我们还是使用之前用到的debug断点调试法来探究一下。

1. 获取Bean源码阅读

我们知道,Spring中获取一个Bean是使用getBean(beanName)来获取,那么我们来跟踪getBean(beanName)的源码,看看获取bean的逻辑,getBean(beanName)的源码如下:

public Object getBean(String name) throws BeansException {
	/**
	 * 该方法执行后进入AbstractRefreshableApplicationContext的assertBeanFactoryActive()方法,
	 * 该方法是一个空方法,所以不用管
	 */
	this.assertBeanFactoryActive();
	//1.先获取容器对象
	ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
	//2.再通过容器beanFactory获取对象
	Object object = beanFactory.getBean(name);
	return object;
}

从源码上可以得到,核心逻辑我们需要阅读this.getBeanFactory().getBean(name)对应的方法。但是这行代码是一个链式调用,this.getBeanFactory()方法得到的ConfigurableListableBeanFactory是一个接口,实际上返回的是他的实现类DefaultListableBeanFactory。调用DefaultListableBeanFactory的getBean方法来获取bean。

2. DefaultListableBeanFactory的getBean方法源码阅读

getBean()的源码中调用的是doGetBean(),这个方法我们在探索创建Bean的时候,有探索过,只是之前探索的是创建Bean的过程,现在需要探索获取bean的过程。贴出源码,源码如下:

public Object getBean(String name) throws BeansException {
	return this.doGetBean(name, (Class)null, (Object[])null, false);
}

3. AbstractBeanFactory的doGetBean()方法源码阅读

doGetBean()方法是获取bean的执行方法,该方法的逻辑很重要。需要仔细阅读,源码如下:

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
	String beanName = this.transformedBeanName(name);
	//该方法执行后,对象就拿到了
	Object sharedInstance = this.getSingleton(beanName);
	Object beanInstance;
	if (sharedInstance != null && args == null) {
		if (this.logger.isTraceEnabled()) {
			if (this.isSingletonCurrentlyInCreation(beanName)) {
				this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
			} else {
				this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
			}
		}

		beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
	} else {
		if (this.isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		BeanFactory parentBeanFactory = this.getParentBeanFactory();
		if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
			String nameToLookup = this.originalBeanName(name);
			if (parentBeanFactory instanceof AbstractBeanFactory) {
				return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
			}

			if (args != null) {
				return parentBeanFactory.getBean(nameToLookup, args);
			}

			if (requiredType != null) {
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}

			return parentBeanFactory.getBean(nameToLookup);
		}

		if (!typeCheckOnly) {
			this.markBeanAsCreated(beanName);
		}

		StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);

		try {
			if (requiredType != null) {
				beanCreation.tag("beanType", requiredType::toString);
			}

			RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
			this.checkMergedBeanDefinition(mbd, beanName, args);
			String[] dependsOn = mbd.getDependsOn();
			String[] var12;
			if (dependsOn != null) {
				var12 = dependsOn;
				int var13 = dependsOn.length;

				for(int var14 = 0; var14 < var13; ++var14) {
					String dep = var12[var14];
					if (this.isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}

					this.registerDependentBean(dep, beanName);

					try {
						this.getBean(dep);
					} catch (NoSuchBeanDefinitionException var31) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
					}
				}
			}

			if (mbd.isSingleton()) {
				sharedInstance = this.getSingleton(beanName, () -> {
					try {
						return this.createBean(beanName, mbd, args);
					} catch (BeansException var5) {
						this.destroySingleton(beanName);
						throw var5;
					}
				});
				beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			} else if (mbd.isPrototype()) {
				var12 = null;

				Object prototypeInstance;
				try {
					this.beforePrototypeCreation(beanName);
					prototypeInstance = this.createBean(beanName, mbd, args);
				} finally {
					this.afterPrototypeCreation(beanName);
				}

				beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			} else {
				String scopeName = mbd.getScope();
				if (!StringUtils.hasLength(scopeName)) {
					throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
				}

				Scope 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, () -> {
						this.beforePrototypeCreation(beanName);

						Object var4;
						try {
							var4 = this.createBean(beanName, mbd, args);
						} finally {
							this.afterPrototypeCreation(beanName);
						}

						return var4;
					});
					beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				} catch (IllegalStateException var30) {
					throw new ScopeNotActiveException(beanName, scopeName, var30);
				}
			}
		} catch (BeansException var32) {
			beanCreation.tag("exception", var32.getClass().toString());
			beanCreation.tag("message", String.valueOf(var32.getMessage()));
			this.cleanupAfterBeanCreationFailure(beanName);
			throw var32;
		} finally {
			beanCreation.end();
		}
	}

	return this.adaptBeanInstance(name, beanInstance, requiredType);
}

4. DefaultSingletonBeanRegistry的getSingleton方法源码阅读

getSingleton()是最终的获取方法,由于对象创建后,会存在singletonObjects中,所以在singletonObjects这个Map获取到后直接返回,源码如下:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	/**
	 * 根据beanName在singletonObjects中获取,
	 * 如果获取到对象信息,即singletonObject != null,
	 * 则返回singletonObject
	 */
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
		singletonObject = this.earlySingletonObjects.get(beanName);
		if (singletonObject == null && allowEarlyReference) {
			synchronized(this.singletonObjects) {
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					singletonObject = this.earlySingletonObjects.get(beanName);
					if (singletonObject == null) {
						ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
						if (singletonFactory != null) {
							singletonObject = singletonFactory.getObject();
							this.earlySingletonObjects.put(beanName, singletonObject);
							this.singletonFactories.remove(beanName);
						}
					}
				}
			}
		}
	}

	return singletonObject;
}

到此,Spring获取Bean的完整流程就全部分析完成了,我们做个总结。结论如下:

  • 首先通过ApplicationContext对象,调用getBean()方法
  • getBean()方法中会先获取BeanFactory实例对象DefaultListableBeanFactory
  • 然后调用BeanFactory的getBean方法
  • getBean()方法中调用doGetBean()方法
  • doGetBean()方法中根据传入的beanName调用getSingleton()方法
  • getSingleton()中根据beanName查询singletonObjects中Value,该Value就是bean对象
  • 查询到bean对象后,返回

以上就是Spring获取bean的所有逻辑流程!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值