Spring 5.x 源码之旅十五getBean详解一

Spring 5.x 源码之旅十五getBean详解一

  • getBean(String name)
  • doGetBean开始获取bean
    • doGetBean分段1
      • AbstractAutowireCapableBeanFactory的getObjectForBeanInstance
      • AbstractBeanFactory的getObjectForBeanInstance
        • getCachedObjectForFactoryBean从缓存里获取
        • getObjectFromFactoryBean创建bean
          • doGetObjectFromFactoryBean
          • beforeSingletonCreation和afterSingletonCreation
          • postProcessObjectFromFactoryBean对创建出来的bean进行处理器处理
    • 实战例子

getBean(String name)

昨天我们讲了单例实例化的时候会先判断是否是FactoryBean类型的,是的话会进行相应处理,但是没讲最关键的getBean,现在我们就开始讲这个,可能需要很多个篇幅,里面涉及了很多东西。废话不多说,我们开始吧。这些是我们要进行实例化的单例:
Spring 5.x 源码之旅十五getBean详解一_第1张图片
但是前面有一些已经被创建出来了,可以直接获取:
Spring 5.x 源码之旅十五getBean详解一_第2张图片
其实我们就只要关心我们自定义的两个对象:
Spring 5.x 源码之旅十五getBean详解一_第3张图片
我们开始吧:
Spring 5.x 源码之旅十五getBean详解一_第4张图片
在这里插入图片描述

doGetBean开始获取bean

我们来看下这个方法的参数:

name 就是bean名字
requiredType 表示需要的类型,如果有类型,创建后会进行类型转换
args 表示参数,也就是构造方法的参数
typeCheckOnly 表示只是做检查,并不是真的要用,这个会影响一些逻辑

因为代码比较长,我们分段来分析比较好,就保留和核心的代码:

doGetBean分段1

首先判断单例存在,且没有参数,这个时候还不能直接返回,还要做一些处理,因为传进来的名字可能是FactoryBean本身,也就是name=&beanName

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		//获取规范的名字
		final String beanName = transformedBeanName(name);
		Object bean;
		//检查是否手动注册了单例
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {//存在单例了
			...
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

AbstractAutowireCapableBeanFactory的getObjectForBeanInstance

这个方法有两个重要的参数namebeanNamename是指传进来的名字,可能是FactoryBean本身的名字,有&前缀,也可能是一般的bean名字,beanName是规范后的名字,去掉了&前缀,所以要进行处理。比如这种:
Spring 5.x 源码之旅十五getBean详解一_第5张图片

	@Override
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		//如果有正在创建的bean要建立以来关系,后面讲
		String currentlyCreatedBean = this.currentlyCreatedBean.get();
		if (currentlyCreatedBean != null) {
			registerDependentBean(beanName, currentlyCreatedBean);
		}

		return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
	}

AbstractBeanFactory的getObjectForBeanInstance

最后调用父类的处理方法,会下判断name是不是FactoryBean自身的名字,如果是,就判断beanInstance 是不是FactoryBean类型的,是的话就直接返回,也就是说,要找的就是FactoryBean自身,而不是他创建的bean。如果不是FactoryBean自身的名字,类型也不是FactoryBean,那就普通的单例,直接返回。否则就是说明应该获取的是FactoryBean创建的bean。如果RootBeanDefinition 不为空的话,设置FactoryBean=true,否则就从FactoryBean的缓存中获取,如果获取到就直接返回,否则就要创建,然后返回。

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		if (BeanFactoryUtils.isFactoryDereference(name)) {//是否是FactoryBean名字的前缀
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {//不是FactoryBean的话名字有&会报异常
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		if (!(beanInstance instanceof FactoryBean)) {//不是FactoryBean就直接返回
			return beanInstance;
		}
		//创建FactoryBean中的bean
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {//从FactoryBean的缓存中获取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {

			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;

			if (mbd == null && containsBeanDefinition(beanName)) {//mbd没定义,但是FactoryBean是有定义的,获取mbd
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getCachedObjectForFactoryBean从缓存里获取

factoryBeanObjectCache就是FactoryBean创建的bean的缓存,创建一次后会进行缓存,下次直接拿。

	@Nullable
	protected Object getCachedObjectForFactoryBean(String beanName) {
		return this.factoryBeanObjectCache.get(beanName);
	}

getObjectFromFactoryBean创建bean

这里就是FactoryBean创建bean的过程。如果FactoryBean是单例,且已经创建出来了,先从缓存里获取看看,如果存在直接返回。如果不存在就进行doGetObjectFromFactoryBean创建,其实就是调用了getObject()获取对象。这里又做了一次从缓存中获取,感觉挺奇怪的,前面已经获取不存在了,这里怎么又能存在,其实是因为getObject()创建的时候可以自定义,可能有处理器处理,可能会对factoryBeanObjectCache进行设置,所以这里还要判断一次,如果存在的话,就应该获取存在的,而不是刚创建的,这样的话处理器才算是有扩展的功能,否则处理了也等于没用。如果没有缓存存在,判断是否是否需要处理,其实这里说的就是不是合成的对象!synthetic,比如AOPadvice通知就算是合成的,一般的对象都不合成的,如果需要处理,但是是正在创建中的单例,直接返回不处理,否则要进行处理器处理,最后放进缓存。如果是原型的话每次都创建一个新的。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {//需要处理
							if (isSingletonCurrentlyInCreation(beanName)) {//直接返回
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);//进行后置处理器处理
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {//如果包含了FactoryBean,就将创建的对象缓存
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {//FactoryBean是原型的话
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}
doGetObjectFromFactoryBean

其实没别的东西,就是调用getObject()创建对象,如果返回null的话,就封装成一个NullBean

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		...
		object = factory.getObject();//调用自定义的FactoryBean的getObject获取对象
		...
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {//如果是正在创建的FactoryBean,还没能获得bean,就报异常
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}
beforeSingletonCreation和afterSingletonCreation

这个就是标记下,正在创建这个bean,创建处理完了就清除标记。

	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);//没有在排除范围里内且添加不成功,可能就是循环引用了
		}
	}

	protected void afterSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
	}
}

postProcessObjectFromFactoryBean对创建出来的bean进行处理器处理

就是进行BeanPostProcessorpostProcessAfterInitialization处理,也就是可以扩展的地方。

	@Override
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
		return applyBeanPostProcessorsAfterInitialization(object, beanName);
	}
	
	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

实战例子

测试例子:
Spring 5.x 源码之旅十五getBean详解一_第6张图片
没有设置原型:
Spring 5.x 源码之旅十五getBean详解一_第7张图片
Spring 5.x 源码之旅十五getBean详解一_第8张图片
设置了原型:
Spring 5.x 源码之旅十五getBean详解一_第9张图片
Spring 5.x 源码之旅十五getBean详解一_第10张图片

可见在FactoryBean上设置了@Scope("prototype")会影响创建的bean

果然讲细了没多少东西好讲,但是不讲清除直接跳过去等于没学什么,走马观花,到头来遇到问题还是得深入探究,学东西还是有点研究精神好。剩下的下篇继续吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

你可能感兴趣的:(Spring,5.x,源码之旅)