Spring容器三级缓存的学习记录

这里做下Spring容器中三级缓存Bean对象创建过程中的应用时机

在这里随便推荐下尚硅谷雷丰阳老师源码级别(可查看目录列表)的对Spring注解的讲解,在其中老师在源码的角度讲解了一遍Spring容器的创建过程(在视频列表偏后面一点)
https://www.bilibili.com/video/av20967380

三级缓存:

  1. 第一级缓存:singletonObjects
  2. 第二级缓存:earlySingletonObjects
  3. 第三级缓存:singletonFactory

Spring容器三级缓存的学习记录_第1张图片

一.完成一个Bean对象的创建需要三步

记录大概过程,其中其实还有创建该Bean依赖的Bean和各种后置处理器的调用等等操作

1.创建Bean实例(createBeanInstance)
-这里主要操作是从之前已经处理好的BeanDefition(Bean定义信息)中实例化一个对象。

2.Bean对象属性赋值(populateBean)
-像@Autowired注解修饰的成员变量是在这一步完成注入的。

3.Bean对象的初始化(初始化Bean实例)
-这一步会去调用这个Bean继承了某些接口(BeanNameAware等)的方法。

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

		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}

		if (instanceWrapper == null) {

			// 创建Bean实例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}

		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		mbd.resolvedTargetType = beanType;

		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;
			}
		}

		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {

			// Bean实例属性赋值
			populateBean(beanName, mbd, instanceWrapper);

			if (exposedObject != null) {

			// 初始化Bean实例
				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<String>(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 " +
								"'getBeanNamesOfType' 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;
	}

二.三级缓存的应用时机

Bean对象在被实例化后会放入第三级缓存(addSingletonFactory

		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

三.二级缓存的应用时机

在Bean对象被放入三级缓存后,以后的操作如果要进入缓存查询,就会将
三级缓存中的Bean对象移动到二级缓存**,此时放入三级缓存的Bean对象会被移除**

	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 != NULL_OBJECT ? singletonObject : null);
	}

四.一级缓存的应用时机

Bean对象创建完毕后会放入一级缓存。(addSingleton
在要用到一个Bean对象之前,都会尝试从缓存中获取最先就是判断一级缓存中存不存在,所以称“一级”。

			try {
					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 != NULL_OBJECT ? singletonObject : null);

五.总结

三级缓存其实就是三个Map,它们在特定的时间特定的场合被使用,以解决特定的问题
(其实整个Spring容器就是许多的Map组成,保存了环境信息、Bean定义信息、Bean实例等等)

文章中有许多地方是自己打断点一步一步调试后对代码的理解,有的地方表达意思不够清楚可能还存在错误,有问题请提出,感谢❤。

你可能感兴趣的:(记录,学习)