Spring对象创建过程

云程序员 2021年01月01日 20次浏览

理解概念

对象创建过程并不难理解,主要的难点是几个概念上的问题。首先观察该方法中用到的该类的几个参数。

单例对象缓存池
/** Cache of singleton objects: bean name --> bean instance */ 
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

如注解,这是Spring的单例对象池,所有的单例对象创建完毕后都会以beanName ->singletonObject 的形式放入该Map集合中

对象预创建标记池
/** Names of beans that are currently in creation */ 
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

这是Spring为了解决循环依赖的一个标记集合,具体概念留在后面介绍

预创建单例对象缓存池

/** Cache of early singleton objects: bean name --> bean instance */

private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

此集合是保存预创建单例对象的集合

预创建单例对象缓存池
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

此集合是保存ObjectFactory的集合

BeanFactory

这是我们大家非常熟悉的接口,Spirng管理Bean容器最原始接口,我们此次研究的入口getBean()就是在此接口中定义。

FactoryBean

在上文2.2中我们已经讨论了FactoryBean的情况,作为一个Bean的工厂对象,它也可以作为一个bean对象直接获取,关于BeanFactory和FactoryBean的详细信息,可查看该文章:BeanFactory和FactoryBean

ObjectFactory

与FactoryBean很相似的是ObjectFactory也是用于创建一个对象的,且它存在的意义主要用于解决循环依赖。例如A、B两个对象,A中有B属性,B中有A属性。那么在创建A时发现需要注入B,这时创建B,在创建B时发现又需要注入A,这就形成了循环依赖。而Spring正是利用ObjectFactory解决了这个问题,其原理就是在创建A时就将一个A的ObjectFactory对象放入了缓存中,那么在B注入A时就用这个ObjectFactory创建的对象注入B中,这样就解决了循环依赖的问题。具体的代码在下面会详细介绍。

BeanDefinition

BeanDefinition是spring bean的建模对象,就是把一个bean实例化出来的模型对象,上面有存在bean的作用域,bean的注入模型,bean是否是懒加载等等信息,Class是无法抽象出来的,故而需要一个BeanDefinition类来抽象这些信息,以便于spring能够完美的实例化一个bean

代码分析

doGetBean(入口)
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        //获取一个bean的名字,过滤特殊字符 
		final String beanName = transformedBeanName(name);
		Object bean;

		// 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 + "'");
				}
			}
			bean = 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);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
                // 保证依赖被初始化,需要注意的事,这个不是注入的依赖,而是@DependOn注解上的依赖,不可以相互依赖
				// 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;
						}
					});
					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();
					final 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;
	}

我们先来大概看一下整体代码,代码的逻辑就是

  1. 先判断之前是否已经创建,如果已经创建了,就直接返回

  2. 如果没有创建,就开始创建,第一步是先创建加载依赖的类

  3. 依赖的类加载完成后,开始创建自己

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

这个代码是通过多级缓存的方式来获取已经创建的bean,也是解决相互依赖的关键,步骤如下

  1. 直接从单例缓存池中获取对象

  2. 如果不存在,而且在创建中,则从预先创建的对象池earlySingletonObjects中获取对象

  3. 如果也不存在,就直接从预先暴露的singletonFactories池中获取,并移动到earlySingletonObjects中

含回调的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 {
					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;
		}
	}

这个方法很简单,就是简单包装了一下创建前后的信息

  1. 创建前将bean放进正在创建的池中,告诉后续有依赖本对象的类,我在创建中了,可以从预先暴露的池中找到我

  2. singletonFactory.getObject()里方法调用create方法创建对象

  3. 创建完成后,从创建池中删除

doCreateBean

接着再来看看最关键的创建方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @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);
		}
		final 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");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			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 " +
								"'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;
	}

这个方法中比较重要的过程是

  1. 预先暴露对象,将对象添加到singletonFactories中,但引用的对象互相引用自己的时候,可以直接将改对象直接返回
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
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);
			}
		}
	}
  1. 处理注入,字段初始化等,方法里面会创建一些引用对象,这里开始递归依赖
populateBean(beanName, mbd, instanceWrapper);
  1. 初始化,前后回调
exposedObject = initializeBean(beanName, exposedObject, mbd);
  1. 处理预创建对象被增强的问题
if (earlySingletonExposure) {
    //尝试从缓存中获取单例,注意后面的参数为false,表示不从第三级缓存singletonFactories中获取,为什么呢?因为这里不允许循环依赖
	Object earlySingletonReference = getSingleton(beanName, false);
	//如果不为null,就会进入if条件中,因为earlySingletonReference不为null,说明存在循环引用,
	//为什么呢?因为第一个处理的时候,会将引用放到singletonFactories缓存中,当循环依赖注入的时候,
	//会通过singletonFactories中拿到提前暴露的引用,然后放到第二级缓存earlySingletonObjects中。
	if (earlySingletonReference != null) {
	    //如果相等,那么就什么也不做,将earlySingletonReference返回回去即可
		if (exposedObject == bean) {
			exposedObject = earlySingletonReference;
		}
		//如果不相等(具体为什么会不相等,下面会单独说),并且有其它bean依赖这个bean
		else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
		    //拿到依赖这个bean的所有bean
			String[] dependentBeans = getDependentBeans(beanName);
			Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
			for (String dependentBean : dependentBeans) {
			    //如果存在已经创建完的bean(依赖这个bean)
				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.");
			}
		}
	}
}

看完代码,有两点需要注意

  1. exposedObject可能会在initializeBean中被改变,所以要先判断是否有改变,没有改变可以直接返回,因为所有类引用的是同一个对象

  2. 如果exposedObject被改变,并且有依赖这个bean的bean已经创建完成,那意味着不是单例了,所以需要报错。

总结

通过上面分析,我们来总结一下Bean的初始化过程

  1. 获取Bean的时候,会尝试从缓存池中获取Bean(多级缓存)

  2. 不存在的情况下就创建Bean

  3. 创建后提前暴露,让相互依赖的对象也可以直接获取使用

  4. 强化对象,回调

  5. 如果强化后的对象和之前暴露的是同一个对象,意味着其他对象也正确引用对象

  6. 如果强化后对象有变更,判断是否存在已经完成的对象,删除依赖本对象的对象,如果存在已完成的对象,则报错。

举个例子

互相依赖

假如B依赖C,C依赖B,代码如下

@Component
public class B {
    @Autowired
    private C c;
    //@Async
    public void test(){

    }
}
@Component
public class C {
    @Autowired
    private B b;
    //@Async
    public void test(){

    }

}

整个流程就是

  1. 先创建B对象

  2. 预先暴露B对象

  3. B引用C,所以开始创建C对象,预暴露C

  4. C引用B,开始获取B,由于B已经暴露,所以C的第二次创建可以直接返回之前预先暴露的对象

  5. C后续回调并完成创建

  6. B后续回调并完成创建

  7. 检查预先暴露的B对象和回调后的对象是否相等

  8. 在这个例子中,两个对象相等,所以直接返回B对象

互相依赖有加强对象1

我们再来看看不能互相依赖的情况
这个例子中,我们打开B类中的@Async

@Component
public class B {
    @Autowired
    private C c;
    @Async
    public void test(){

    }
}

由于@Async有进行对象B加强,返回代理对象,所以上述第7步的两个对象不相等,并且C已经完成创建,所以会有下面的报错

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'b': Bean with name 'b' has been injected into other beans [c] 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.
互相依赖有加强对象2

还有一种特殊情况是没问题的,就是我们保持B的对象是没有被@Async加强的,而C代码是被加强的

@Component
public class C {
    @Autowired
    private B b;
    @Async
    public void test(){

    }

}

这种情况没有出现报错,是因为初始化是由B到C的,所以B引用的C会先完成最后初始化,B对象最后没有被加强,最终没有出现报错