sping源码解读(三)

本篇我们重点讲下getBean流程

然后我们重点看下这个doGetBean方法

我们重点看下这个getSingleton方法

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

上述的singletonObject 其实就是我们所说的容器,但也不完全是,更准确的说法叫单例缓存池,也就是存放我们的单例对象的地方,比如我们经常写得service  controller等

singletonObjects本质上是一个map

/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

取bean的逻辑我们清楚了,但是我们要知道他是什么时候put进去的呢?我们利用idea全局搜索一下this.singletonObjects.put得到以下结果,我们再上面打个断点,再加个条件

运行后得到以下栈信息:

我们先查看栈线程,发现源头是由main方法发出的,我们看下main方法的第九行

发现就是在初始化容器的时候加载bean对象的,然后我们重点看下getBean这个方法,一步步去深入研究,我们重点看下doGetBean方法,下面是源码

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
        //转换别名<bean alias="xxx">
		String beanName = transformedBeanName(name);
		Object bean;

		// 从容器中取对象,此时为null,因为此时容器为空
		Object sharedInstance = getSingleton(beanName);
        //为null直接跳过
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			//判断是否为原型,肯定为false,因为我们是单例模式,跳过
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			//这个是检查是否有父容器,我们没有,直接跳过
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

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

			try {
                //获取bean定义
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //检查是不是由abstract属性,有就抛异常
                //<bean id="" abstract="true" class="" />
				checkMergedBeanDefinition(mbd, beanName, args);
                //获取dependsOn属性的类
                //dependsOn是指有依赖关系的类,如果有该属性则会暂时停止当前对象的实例化,
                //先去实例有依赖关系的dependsOn属性的类,我们这里没有,跳过
				String[] dependsOn = mbd.getDependsOn();
				if (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);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// 检查bean定义是否为单例模式,我们这里是,所以为true
				if (mbd.isSingleton()) {
                    //该方法是直接实例化对象的方法,直接返回instD对象的
                    //并且该方法是将实例化的对象放至一级缓存中,并删除二三级缓存
					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();
					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);
							}
						});
						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;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

我们再来看下getSingleton方法,看是如何实例化对象的

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
           //先从一级缓存中取,如果取到了就直接返回
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
                    //创建bean,这个地方实际上调用了creatBean方法
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
                    //放至缓存池中
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

再来看看addSingleton方法:

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
            //将实例对象放至一级缓存
			this.singletonObjects.put(beanName, singletonObject);
            //移除三级缓存
			this.singletonFactories.remove(beanName);
            //移除二级缓存
			this.earlySingletonObjects.remove(beanName);
            //用来记录保存已经处理的bean
			this.registeredSingletons.add(beanName);
		}
	}

我们再来看看docrate Bean方法,此方法是真实创建bean对象的方法

循环依赖的解决方式是比如A和B对象相互依赖,但是容器在实例化A将B(此时B未被实例化)注入的时候,会去调用getBean方法实例化B,和实例化A的逻辑一样,但是实例化B的时候又发现依赖A,这时又去getBean(A),但和第一次不一样,因为这次走到getSingleton()方法时,发现缓存中已经有A的实例对象,直接取就行,不需要和第一次一样重新实例化,大概逻辑如图所示:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
        //创建一个空对象(早期对象,没有赋值),通过反射创建对象
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		//解决循环依赖的核心逻辑
        //判断bean定义是单例且默认为true,且当前创建对象是自己本身  返回true
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
            //将早期对象放至三级缓存中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
            //给早期对象的属性赋值,如果有循环依赖,那就可以将A对象注入B,B注入A中
            //使用构造器注入时,会在此处产生递归操作,在第四层创建A时 
            //DefaultSingletonBeanRegistry的beforeSingletonCreation方法中会报错
		    //因为DefaultSingletonBeanRegistry的this.singletonFactories中没有A的bean缓存。 
            //所以在beforeSingletonCreation中便会报错。
		    //那么为什么用属性注入时就不会报错呢?因为this.singletonFactories缓存发生在当前方 
            //法的addSingletonFactory行,而属性注入的递归发生在这一行,也就是说 先进行了缓存。 
            //而构造器注入时 还没来得及缓存就已经递归到下一层了。
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

        //如果是循环依赖
		if (earlySingletonExposure) {
            //移除三级缓存放至二级缓存
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

再看下addSingletonFactory方法,是如何暴露早期对象的?

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
            //判断一级缓存是否存在
			if (!this.singletonObjects.containsKey(beanName)) {
                //放至三级缓存中
				this.singletonFactories.put(beanName, singletonFactory);
                //从二级缓存中移除
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

思考:为什么要将对象放到三级缓存中呢?我们先看看三级缓存有什么不同?

再来回顾下三级缓存存放的时候会调用 getEarlyBeanReference方法

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

这个方法的作用就是自动注入循环依赖的代理对象,代理对象的好处就是支持事务。

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

我们再回看getSingleton方法:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //先从一级缓存
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                //从二级缓存里拿
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
                        //把早期对象放至二级缓存
						this.earlySingletonObjects.put(beanName, singletonObject);
                        //移除三级缓存
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

所以为什么要使用三级缓存,目的就是生成代理对象

 

>org.springframework.beans.factory.support.AbstractBeanFactory#getBean

>org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

   1:org.springframework.beans.factory.support.AbstractBeanFactory#transformedBeanName===>转换别名

   2:org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition=>获取当前的bean定义

   3:org.springframework.beans.factory.support.AbstractBeanFactory#checkMergedBeanDefinition==>检查bean是否有abstract属性

   4:org.springframework.beans.factory.support.AbstractBeanDefinition#getDependsOn==>检查dependsOn属性

>org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton==>返回instD实例对象

>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

  >org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

     >org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance===>通过反射创建对象

     >org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory=====>暴露我们的早期对象(上一步创建的空壳对象:属性还没赋值)

     >org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean=====>给上面早期对象赋值

总结:

所有的对象在创建过程中,都会将早期对象暴露到三级缓存中,

针对代理对象,从三级缓存到二级缓存会经过一次代理,

创建完成之后,就会将对象移至单例缓存池(一级缓存),并删除二级缓存

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值