SpringIOC的三级缓存原理分析

前言

看本篇文章之前需要了解SpringIOC的基本流程,不了解的可以看我的这篇SpringIOC源码详解

一. 什么是SpringIOC的三级缓存

类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。
如下图是三个类之间的循环依赖
在这里插入图片描述
Spring 的依赖注入方式有三种:构造方法注入setter 方法注入接口注入

  • setter 方法注入的方式,是在对象实例化完成之后,再通过反射调用对象的 setter 方法完成属性的赋值,能够处理循环依赖的问题,也是本文要讲的
  • 构造方法注入的方式,将实例化与初始化并在一起完成,能够快速创建一个可直接使用的对象,但它没法处理循环依赖的问题,类似先有鸡还是先有蛋的问题
  • 接口注入的方式太灵活,易用性比较差,所以并未广泛应用起来

二. 跟着栗子看源码

下面这个栗子是两个类的相互依赖,同样能看出来三级缓存的流程
Animal类:

public class Animal {

    private String name;

    private Fruits fruits;

    public Fruits getFruits() {
        return fruits;
    }

    public void setFruits(Fruits fruits) {
        this.fruits = fruits;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Fruits类:

public class Fruits {

    private String name;

    private Animal animal;

    public Animal getAnimal() {
        return animal;
    }

    public void setAnimal(Animal animal) {
        this.animal = animal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

SpringBean的XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

    <bean id="fruits" class="com.jingchuan.model.Fruits">
        <property name="name" value="banana"></property>
        <property name="animal" ref="animal"></property>
    </bean>
    <bean id="animal" class="com.jingchuan.model.Animal">
        <property name="name" value="monkey"></property>
        <property name="fruits" ref="fruits"></property>
    </bean>

</beans>

测试:

import com.jingchuan.model.Fruits;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestIoc {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationIoc.xml");
        Fruits fruits = (Fruits) context.getBean("fruits");
        System.out.println(fruits.getName());
    }

}

上面的测试代码配了两个Bean:FruitsAnimal,他们相互依赖对方

三. 源码分析

三级缓存分别是啥:

/** Cache of singleton objects: bean name to bean instance. */
// 一级缓存   存的是完整的对象 已经解决了循环依赖和属性赋值等问题的最终对象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
// 三级缓存   存的是通过ObjectFactory对象来存储单例模式下提前暴露的Bean实例的引用(正在创建中) 
// 其中ObjectFactory包含了对象的一系列包装的功能,比如代理
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
// 二级缓存  存的是单例模式下创建的Bean实例,该Bean被提前暴露的引用,该Bean还在创建中
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

通过之前对SpringIOC源码详解的了解之后,应该知道在org.springframework.context.support.AbstractApplicationContext#refresh方法中对bean对象进行了注册和实例化。本篇我们直接从实例化开始讲,直接来到org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法,我们跟着上面的例子跟源码:

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

	String beanName = transformedBeanName(name);
	Object beanInstance;
	
	// Eagerly check singleton cache for manually registered singletons.
	// 从缓存中取对象  这里面就是根据参数从三级缓存中依次取对象
	Object sharedInstance = getSingleton(beanName);
	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 + "'");
			}
		}
		beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

	else {
		// Fail if we're already creating this bean instance:
		// We're assumably within a circular reference.
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// Check if bean definition exists in this factory.
		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);
		}

		StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
				.tag("beanName", name);
		try {
			if (requiredType != null) {
				beanCreation.tag("beanType", requiredType::toString);
			}
			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// Guarantee initialization of beans that the current bean depends on.
			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);
					}
				}
			}

			// Create bean instance.
			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;
					}
				});
				beanInstance = 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);
				}
				beanInstance = 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);
						}
					});
					beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
				}
				catch (IllegalStateException ex) {
					throw new ScopeNotActiveException(beanName, scopeName, ex);
				}
			}
		}
		catch (BeansException ex) {
			beanCreation.tag("exception", ex.getClass().toString());
			beanCreation.tag("message", String.valueOf(ex.getMessage()));
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
		finally {
			beanCreation.end();
		}
	}

	return adaptBeanInstance(name, beanInstance, requiredType);
}

我们上面例子中有两个相互依赖的对象fruitsanimal,当实例化fruits对象时,第一步会走到Object sharedInstance = getSingleton(beanName);,这里取出来肯定是空的,因为我们的对象从来没有实例化过,然后继续往下跟代码经过一系列的判断会走到单例对象的创建。

// Create bean instance.
if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			// 创建bean实例
			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;
		}
	});
	beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

在这个if里面可以看到先执行getSingleton这个方法,参数是类名和一个lambda表达式的函数参数ObjectFactory<?> singletonFactory,在getSingleton里面经过调用最终还是会来到这个lambda表达式的函数执行createBean(beanName, mbd, args),继续跟进回来到:

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

	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		// 这里是创建接口等对象的,类似mybatis的Mapper接口 直接略过
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		// 执行这里创建实例
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

在这个方法中继续跟进到Object beanInstance = doCreateBean(beanName, mbdToUse, args);

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) {
		// 实例化bean对象  这里实例化出来的是空对象   只有实例没有设置属性的
		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;
		}
	}

	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	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");
		}
		// 处理循环依赖问题  这里是先把这个bean名称和bean的ObjectFactory<?>存入三级缓存
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		// 开始处理bean的属性赋值
		populateBean(beanName, mbd, instanceWrapper);
		// 赋值完成后开始回调init方法和处理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<>(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;
}

上面这个方法中,我们简要来看重点步骤:

  1. 第一步:instanceWrapper = createBeanInstance(beanName, mbd, args);反射创建bean实例,
  2. 第二步:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));把这个bean加入三级缓存,三级缓存中缓存的是bean名称对应的ObjectFactory
  3. 第三步:populateBean(beanName, mbd, instanceWrapper);给bean的属性赋值,这一步的过程中遇到对其他对象的引用时,就会进入循环引用的问题

现在我们跟进看populateBean(beanName, mbd, instanceWrapper);,然后这个方法中获取到一个PropertyValues,这个PropertyValues包含当前对象的所有属性信息。
然后进入org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues方法:

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
	if (pvs.isEmpty()) {
		return;
	}

	if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
		((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
	}

	MutablePropertyValues mpvs = null;
	List<PropertyValue> original;

	if (pvs instanceof MutablePropertyValues) {
		mpvs = (MutablePropertyValues) pvs;
		if (mpvs.isConverted()) {
			// Shortcut: use the pre-converted values as-is.
			try {
				bw.setPropertyValues(mpvs);
				return;
			}
			catch (BeansException ex) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Error setting property values", ex);
			}
		}
		// 把当前对象的属性信息赋值给original 
		original = mpvs.getPropertyValueList();
	}
	else {
		original = Arrays.asList(pvs.getPropertyValues());
	}

	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}
	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

	// Create a deep copy, resolving any references for values.
	List<PropertyValue> deepCopy = new ArrayList<>(original.size());
	boolean resolveNecessary = false;
	// 循环当前对象的属性,进行赋值处理
	for (PropertyValue pv : original) {
		if (pv.isConverted()) {
			deepCopy.add(pv);
		}
		else {
			String propertyName = pv.getName();
			Object originalValue = pv.getValue();
			if (originalValue == AutowiredPropertyMarker.INSTANCE) {
				Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
				if (writeMethod == null) {
					throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
				}
				originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
			}
			// 根据属性的信息和值经过处理返回实际的value  这个下面会详细说
			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
			Object convertedValue = resolvedValue;
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			if (convertible) {
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
			}
			// Possibly store converted value in merged bean definition,
			// in order to avoid re-conversion for every created bean instance.
			if (resolvedValue == originalValue) {
				if (convertible) {
					pv.setConvertedValue(convertedValue);
				}
				deepCopy.add(pv);
			}
			else if (convertible && originalValue instanceof TypedStringValue &&
					!((TypedStringValue) originalValue).isDynamic() &&
					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
				pv.setConvertedValue(convertedValue);
				deepCopy.add(pv);
			}
			else {
				resolveNecessary = true;
				deepCopy.add(new PropertyValue(pv, convertedValue));
			}
		}
	}
	if (mpvs != null && !resolveNecessary) {
		mpvs.setConverted();
	}

	// Set our (possibly massaged) deep copy.
	try {
		// 经过上面循环获取对象所有属性的值之后,一次把所有属性set进去
		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
	}
}

上面这个方法里中,先拿到当前对象的所有属性,然后循环处理获取每个属性的值
那么在我们上面的IOC例子中,fruits对象有两个属性,一个是String类型的name,一个是依赖的其他对象animal,对于这两个属性的真实值获取,是在Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);这行代码中处理的:

public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
	// We must check each value to see whether it requires a runtime reference
	// to another bean to be resolved.
	// 处理运行时对象引用
	if (value instanceof RuntimeBeanReference) {
		RuntimeBeanReference ref = (RuntimeBeanReference) value;
		return resolveReference(argName, ref);
	}
	else if (value instanceof RuntimeBeanNameReference) {
		String refName = ((RuntimeBeanNameReference) value).getBeanName();
		refName = String.valueOf(doEvaluate(refName));
		if (!this.beanFactory.containsBean(refName)) {
			throw new BeanDefinitionStoreException(
					"Invalid bean name '" + refName + "' in bean reference for " + argName);
		}
		return refName;
	}
	else if (value instanceof BeanDefinitionHolder) {
		// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
		BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
		return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
	}
	else if (value instanceof BeanDefinition) {
		// Resolve plain BeanDefinition, without contained name: use dummy name.
		BeanDefinition bd = (BeanDefinition) value;
		String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
				ObjectUtils.getIdentityHexString(bd);
		return resolveInnerBean(argName, innerBeanName, bd);
	}
	else if (value instanceof DependencyDescriptor) {
		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		Object result = this.beanFactory.resolveDependency(
				(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
		for (String autowiredBeanName : autowiredBeanNames) {
			if (this.beanFactory.containsBean(autowiredBeanName)) {
				this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
			}
		}
		return result;
	}
	else if (value instanceof ManagedArray) {
		// May need to resolve contained runtime references.
		ManagedArray array = (ManagedArray) value;
		Class<?> elementType = array.resolvedElementType;
		if (elementType == null) {
			String elementTypeName = array.getElementTypeName();
			if (StringUtils.hasText(elementTypeName)) {
				try {
					elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
					array.resolvedElementType = elementType;
				}
				catch (Throwable ex) {
					// Improve the message by showing the context.
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Error resolving array type for " + argName, ex);
				}
			}
			else {
				elementType = Object.class;
			}
		}
		return resolveManagedArray(argName, (List<?>) value, elementType);
	}
	else if (value instanceof ManagedList) {
		// May need to resolve contained runtime references.
		return resolveManagedList(argName, (List<?>) value);
	}
	else if (value instanceof ManagedSet) {
		// May need to resolve contained runtime references.
		return resolveManagedSet(argName, (Set<?>) value);
	}
	else if (value instanceof ManagedMap) {
		// May need to resolve contained runtime references.
		return resolveManagedMap(argName, (Map<?, ?>) value);
	}
	else if (value instanceof ManagedProperties) {
		Properties original = (Properties) value;
		Properties copy = new Properties();
		original.forEach((propKey, propValue) -> {
			if (propKey instanceof TypedStringValue) {
				propKey = evaluate((TypedStringValue) propKey);
			}
			if (propValue instanceof TypedStringValue) {
				propValue = evaluate((TypedStringValue) propValue);
			}
			if (propKey == null || propValue == null) {
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Error converting Properties key/value pair for " + argName + ": resolved to null");
			}
			copy.put(propKey, propValue);
		});
		return copy;
	}
	else if (value instanceof TypedStringValue) {
		// Convert value to target type here.
		// 处理String类型的值
		TypedStringValue typedStringValue = (TypedStringValue) value;
		Object valueObject = evaluate(typedStringValue);
		try {
			Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
			if (resolvedTargetType != null) {
				return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
			}
			else {
				return valueObject;
			}
		}
		catch (Throwable ex) {
			// Improve the message by showing the context.
			throw new BeanCreationException(
					this.beanDefinition.getResourceDescription(), this.beanName,
					"Error converting typed String value for " + argName, ex);
		}
	}
	else if (value instanceof NullBean) {
		return null;
	}
	else {
		return evaluate(value);
	}
}

对于上面这个方法,就是一系列的if else判断循环中每个属性分别是那种类型,对应做不同的处理。而我们上面例子中fruits对象两个属性nameanimal:

  • name是个String类型的,所以会走到TypedStringValue这个else if中,最终返回String类型的value
  • animal属于引用其他的对象,所以会走到第一个RuntimeBeanReference的if判断中
    所以我们重点跟 animal属性的处理:resolveReference(argName, ref)
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
	try {
		Object bean;
		Class<?> beanType = ref.getBeanType();
		if (ref.isToParent()) {
			BeanFactory parent = this.beanFactory.getParentBeanFactory();
			if (parent == null) {
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Cannot resolve reference to bean " + ref +
								" in parent factory: no parent factory available");
			}
			if (beanType != null) {
				bean = parent.getBean(beanType);
			}
			else {
				bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
			}
		}
		else {
			String resolvedName;
			if (beanType != null) {
				NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
				bean = namedBean.getBeanInstance();
				resolvedName = namedBean.getBeanName();
			}
			else {
				resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
				bean = this.beanFactory.getBean(resolvedName);
			}
			this.beanFactory.registerDependentBean(resolvedName, this.beanName);
		}
		if (bean instanceof NullBean) {
			bean = null;
		}
		return bean;
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				this.beanDefinition.getResourceDescription(), this.beanName,
				"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
	}
}

在这个方法中,由于我们的配置中没有BeanType等属性,所以会走到

resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
bean = this.beanFactory.getBean(resolvedName);

那么了解IOC的同学应该就知道这个代码其实就是从Spring的Bean工厂中获取一个bean,所以看到这里,大家应该明白目前在我们的例子中,我们是在实例化fruits这个对象之后(fruits对象已经已ObjectFactory的形式被加入三级缓存中了),现在是在填充他的属性值,这个时候他有一个属性animal是另一个我们配置的Spring中的对象,所以在上面这里又去工厂中找animal对象了
那么这个时候肯定是继续跟着this.beanFactory.getBean(resolvedName)加载下一个animal对象了,这里就不一个一个继续跟了,否则又得跟一遍IOC的getBean的流程,我们简单文字描述一下吧:
在加载fruits对象依赖的animal属性时,发现animal是一个对象就去spring工厂中找这个对象发现这个对象还没被实例化,然后就开始实例化animal对象,在实例化之后还是会把animal对象和fruits一样已ObjectFactory加入三级缓存中,然后再设置animal的属性,当发现animal对象里面有个fruits属性之后就和上面的流程一样又开始去工厂里面找fruits对象。
这个时候会发现fruits对象在工厂的三级缓存中存在的,然后就会从三级缓存中拿出ObjectFactory,并调用getObject()方法获取之前的实例,然后把这个实例存在二级缓存中并从三级缓存中删除
。这个从三级缓存中取的代码在:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean的开始位置的Object sharedInstance = getSingleton(beanName);这个方法里面调用的:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// Quick check for existing instance without full singleton lock
	Object singletonObject = this.singletonObjects.get(beanName);
	// 先从一级缓存中取,没取到但是这个对象正在创建中的话
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		// 在二级缓存中取
		singletonObject = this.earlySingletonObjects.get(beanName);
		//还没取到 并且allowEarlyReference为true的话
		if (singletonObject == null && allowEarlyReference) {
			synchronized (this.singletonObjects) {
				// Consistent creation of early reference within full singleton lock
				// 再从一级缓存中取 但是这里是加锁的,保证单例
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					//再从二级中取
					singletonObject = this.earlySingletonObjects.get(beanName);
					if (singletonObject == null) {
						// 然后最后从三级中取,取出来ObjectFactory
						ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
						if (singletonFactory != null) {
							// 调用getObject从工厂中获取单例对象实例
							singletonObject = singletonFactory.getObject();
							// 加入二级缓存
							this.earlySingletonObjects.put(beanName, singletonObject);
							// 从三级缓存中移除
							this.singletonFactories.remove(beanName);
						}
					}
				}
			}
		}
	}
	return singletonObject;
}

上面这个代码中从三级缓存中取出来ObjectFactory并调用了getObject()方法,这个方法就是org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));里面加入的这个的() -> getEarlyBeanReference(beanName, mbd, bean),这是一个函数式的写法。这里不理解的可以跟着断点走一遍就明白了

然后我们就获取到了fruits对象的实例,只不过这个对象是个没有创建完成的对象,他只有实例,里面的属性都是空的,然后把这个fruits对象的引用返回到创建animal对象过程中的org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveReference,再返回到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValuesObject resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);这一步,这个时候animal对象的fruits属性的值就获取到了,只不过这个fruits是个正在创建过程中的对象,但是animal只需要fruits的引用,所以不影响后续的使用,再接着把这个引用set到属性里就可以了。

然后在继续完成animal对象的创建,代码会一步一步回到org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)这个方法里面,在这个方法里面之前我们讲到了singletonObject = singletonFactory.getObject();这一步是通过工厂获取fruits对象实例,那么现在我们获取到实例之后继续往下走:

  • 在方法的尾部有一步afterSingletonCreation(beanName);,这个实际上是标记这个animal对象已经创建完成,就是从正在创建的对象集合中把刚才已经创建完成的这个对象移除掉。
  • 在方法的最后会有一步:addSingleton(beanName, singletonObject);,这一步是在animal实例已经获取到并且属性已完成设置之后,那么这时候这个animal对象就已经算是创建完成了,所以把这个fruits放入一级缓存,并从二级和三级中删除。

到这里animal对象就算创建完成了,并且已经放到了一级缓存中

然后接下来就回到了fruits对象创建过程中,我们目前创建完了fruitsanimal属性,然后把animal属性set到fruits对象里面,那这个时候fruits对象也创建完成了,然后一步一步返回再次来到org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)方法里面,和上面创建animal对象完成之后一样,这次是把fruits对象通过afterSingletonCreation(beanName);标记为已创建完成,再通过addSingleton(beanName, singletonObject);fruits对象加入到一级缓存并从二级三级里面删除。
至此,fruits对象也创建完成。

然后代码会继续去根据配置文件加载animal对象,但是这个时候animal对象已经实例化完成了,所以直接从一级缓存中拿出已经创建好的实例返回就完成了。

好了!至此animalfruits相互依赖的循环依赖场景就分析完成了,再来个小的步骤总结:

  1. 根据配置文件加载fruits,实例化fruits对象完成并通过ObjectFactory加入三级缓存,后开始设置fruits对象的属性,发现有引用其他对象animal
  2. 因为fruits实例化时引用了animal对象,所以开始实例化animal对象,实例化完成后把animal对象加入三级缓存并开始设置animal的属性,在设置属性时发现他引用了已经在三级缓存中的fruits对象对应的ObjectFactory,所以从三级缓存中取出ObjectFactory并获取到fruits的引用,然后把fruits加入二级缓存并从三级缓存中删除,最后把fruits这个半对象(未实例化完成)设置给animal的属性
  3. 由于animal对象已经实例化完成并设置完成属性, 所以把animal对象加入一级缓存
  4. animal创建完成回到fruits获取属性并设值的阶段,把创建好的animal对象设置到fruits的属性中,完成fruits的创建
  5. fruits对象加入一级缓存
  6. 再次根据配置文件加载animal对象发现已经存在与一级缓存

这个过程有点绕,大家主要还是要多理解IOC的过程,然后自己跟着断点多走几遍就理解了。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值