spring容器-启动流程、创建bean、创建依赖bean:源码分析

896 阅读1分钟

启动流程

核心步骤

1.应用程序的入口
启动项目。

2.创建BeanDefinition,然后写到容器类的BeanDefinition集合里去(具体数据结构是一个map)
通过注解或者读xml文件的方式,得到BeanDefinition。

3.创建bean实例对象
非业务bean(即spring框架里自带的各种bean),一般都提前创建实例,即在启动的时候就创建了。

方法调用栈

resolveBean:407, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBean:341, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBean:335, DefaultListableBeanFactory (org.springframework.beans.factory.support) 

getConfigurableWebBindingInitializer:538, WebMvcAutoConfiguration$EnableWebMvcConfiguration (org.springframework.boot.autoconfigure.web.servlet)
requestMappingHandlerAdapter:564, WebMvcConfigurationSupport (org.springframework.web.servlet.config.annotation)
requestMappingHandlerAdapter:484, WebMvcAutoConfiguration$EnableWebMvcConfiguration (org.springframework.boot.autoconfigure.web.servlet)
CGLIB$requestMappingHandlerAdapter$4:-1, WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$6dc0a0b8 (org.springframework.boot.autoconfigure.web.servlet)
invoke:-1, WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$6dc0a0b8$$FastClassBySpringCGLIB$$51fe5d3e (org.springframework.boot.autoconfigure.web.servlet)
invokeSuper:244, MethodProxy (org.springframework.cglib.proxy)
intercept:363, ConfigurationClassEnhancer$BeanMethodInterceptor (org.springframework.context.annotation)
requestMappingHandlerAdapter:-1, WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$6dc0a0b8 (org.springframework.boot.autoconfigure.web.servlet)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
instantiate:154, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiate:622, ConstructorResolver (org.springframework.beans.factory.support)
instantiateUsingFactoryMethod:607, ConstructorResolver (org.springframework.beans.factory.support)
instantiateUsingFactoryMethod:1321, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1160, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:555, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:515, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:320, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 596910004 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$160)
getSingleton:222, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:318, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support) //创建非业务bean,即spring框架里自带的各种bean

preInstantiateSingletons:849, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:877, AbstractApplicationContext (org.springframework.context.support)
refresh:549, AbstractApplicationContext (org.springframework.context.support)
refresh:142, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:775, SpringApplication (org.springframework.boot)
refreshContext:397, SpringApplication (org.springframework.boot)
run:316, SpringApplication (org.springframework.boot)
run:1260, SpringApplication (org.springframework.boot)
run:1248, SpringApplication (org.springframework.boot)

main:58, SampleTomcatApplication (sample.tomcat) //应用程序的入口

bean实例对象存储在哪里?

源码

/**
 * Generic registry for shared bean instances, implementing the
 * {@link org.springframework.beans.factory.config.SingletonBeanRegistry}.
 * Allows for registering singleton instances that should be shared
 * for all callers of the registry, to be obtained via bean name.
 *
 * <p>Also supports registration of
 * {@link org.springframework.beans.factory.DisposableBean} instances,
 * (which might or might not correspond to registered singletons),
 * to be destroyed on shutdown of the registry. Dependencies between
 * beans can be registered to enforce an appropriate shutdown order.
 *
 * <p>This class mainly serves as base class for
 * {@link org.springframework.beans.factory.BeanFactory} implementations,
 * factoring out the common management of singleton bean instances. Note that
 * the {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
 * interface extends the {@link SingletonBeanRegistry} interface.
 *
 * <p>Note that this class assumes neither a bean definition concept
 * nor a specific creation process for bean instances, in contrast to
 * {@link AbstractBeanFactory} and {@link DefaultListableBeanFactory}
 * (which inherit from it). Can alternatively also be used as a nested
 * helper to delegate to.
 *
 * @author Juergen Hoeller
 * @since 2.0
 * @see #registerSingleton
 * @see #registerDisposableBean
 * @see org.springframework.beans.factory.DisposableBean
 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory
 */
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

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

/**
	 * Add the given singleton object to the singleton cache of this factory.
	 * <p>To be called for eager registration of singletons.
	 * @param beanName the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject); //添加bean实例到map
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

依赖bean存储在哪里?

不管是bean,还是bean的依赖bean/注入bean,都分2个部分
1.bean定义
2.bean实例对象

依赖数据也是bean,所以也是一样。

而且最为重要的一点是,因为bean定义和bean实例对象是2个不同的东西,而且存储的地方也不一样。

所以容器的几个核心问题就是下面的几点。

1.bean定义

xml bean定义映射为BeanDefinition类的对象,BeanDefinition对象专门有一个map存储,这个map就是容器核心实现类DefaultListableBeanFactory的属性beanDefinitionMap。

2.bean实例对象

第一次用的时候,容器会创建bean实例对象,然后存储在DefaultSingletonBeanRegistry的属性singletonObjects。

3.依赖bean的定义

存储在这里,也是存储在map里。注意,这里存储的只是依赖bean的名字,而不是依赖bean实例对象。

DefaultSingletonBeanRegistry

/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16); //被依赖的bean

	/** Map between dependent bean names: bean name to Set of dependent bean names. */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); //依赖的bean
    
    
/**
	 * Return the names of all beans which depend on the specified bean, if any.
	 * @param beanName the name of the bean
	 * @return the array of dependent bean names, or an empty array if none
	 */
	public String[] getDependentBeans(String beanName) { //获取依赖bean
		Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
		if (dependentBeans == null) {
			return new String[0];
		}
		synchronized (this.dependentBeanMap) {
			return StringUtils.toStringArray(dependentBeans);
		}
	}

应用程序可以通过以下方法打印出来。

@GetMapping("/getBeanDefinitionNames")
	public void getBeanDefinitionNames() {
		log.info("start");
		log.info("bean数量:" + applicationContext.getBeanDefinitionCount());
		log.info("bean名字:" + JSONObject.toJSONString(applicationContext.getBeanDefinitionNames()));

		//
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); //获取容器
		log.info("sampleController:" + defaultListableBeanFactory.getBean("sampleController").getClass()); //获取bean
		log.info("被依赖的bean:" + JSONObject.toJSONString(defaultListableBeanFactory.getDependentBeans("sampleController")));
		log.info("依赖的bean:" + JSONObject.toJSONString(defaultListableBeanFactory.getDependenciesForBean("sampleController")));
	}

(这张类继承图,标注了以上数据被存储在了哪个类)

4.依赖bean实例对象

何时创建?


存储在哪里?

也是和bean一样,存储在容器实现类的map里去,因为依赖bean也是bean,和宿主bean完全一样,没有任何区别。唯一的区别,就是依赖关系的区别。

从这张图可以看出来,核心流程是
1.创建bean实例
2.创建注入bean实例
1)和创建bean实例的流程完全一样,因为本来就是一个递归创建,即创建bean,然后再创建bean的依赖bean,一直这样递归下去,直到最后一个依赖bean没有自己的依赖bean为止。
2)并且,还要添加依赖关系,即把依赖bean添加到宿主bean的依赖bean-map里去。依赖bean-map,只是存储了宿主bean名字和依赖bean名字集合。不是存储依赖bean实例对象,因为依赖bean实例对象的存储是和宿主bean的存储是在同一个地方,即都是在存储容器实现类的bean-map里。

(这张类继承图,标注了以上数据被存储在了哪个类)

以上存储内容和BeanDefinition存储内容的区别和对比?

BeanDefinition

是什么?是xml bean的映射。 包含了什么内容?比如,包含了bean名字。

BeanDefinition实现类的类继承图


bean的属性存储在这里

每个属性的本质其实就是属性名字和属性的值,属性名字就是变量名字,属性的值就是类的名字,而不是实际的实例对象。

这里的属性存储的是是所有属性?还是只是依赖bean?
只是依赖bean属性,其他属性不存储,因为创建bean的依赖bean的实例对象的时候,是根据这个属性来创建的。由此可见,BeanDefinition是创建bean实例和创建依赖bean实例的一个基础依据,即定义了bean和它的依赖bean,虽然这里不是真正创建bean实例的地方,但是真正创建bean实例和依赖bean的实例对象的时候,都是根据BeanDefinition这里的定义来创建的。

容器实现类DefaultListableBeanFactory

bean实例对象

bean的依赖bean

和bean完全一样

源码分析

创建bean实例对象

创建依赖bean的实例对象


/**
	 * Populate the bean instance in the given BeanWrapper with the property values
	 * from the bean definition.
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @param bw the BeanWrapper with bean instance
	 */
	@SuppressWarnings("deprecation")  // for postProcessPropertyValues
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //获取bean属性

		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) { //如果bean属性不为空,就创建依赖bean的实例对象
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

/**
	 * Apply the given property values, resolving any runtime references
	 * to other beans in this bean factory. Must use deep copy, so we
	 * don't permanently modify this property.
	 * @param beanName the bean name passed for better exception information
	 * @param mbd the merged bean definition
	 * @param bw the BeanWrapper wrapping the target object
	 * @param pvs the new property values
	 */
	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 = 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();
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); //创建依赖bean的实例对象
				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 {
			bw.setPropertyValues(new MutablePropertyValues(deepCopy)); //
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}

创建依赖bean的实例对象,后面的流程和创建bean完全一样。

/**
	 * Resolve a reference to another bean in the factory.
	 */
	@Nullable
	private Object resolveReference(Object argName, RuntimeBeanReference ref) {
		try {
			Object bean;
			String refName = ref.getBeanName();
			refName = String.valueOf(doEvaluate(refName));
			if (ref.isToParent()) {
				if (this.beanFactory.getParentBeanFactory() == null) {
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Can't resolve reference to bean '" + refName +
							"' in parent factory: no parent factory available");
				}
				bean = this.beanFactory.getParentBeanFactory().getBean(refName);
			}
			else {
				bean = this.beanFactory.getBean(refName); //创建依赖bean的实例对象
				this.beanFactory.registerDependentBean(refName, this.beanName); //添加依赖bean到map里去
			}
			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);
		}
	}

方法调用栈

getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support) //创建依赖bean的实例对象

resolveReference:367, BeanDefinitionValueResolver (org.springframework.beans.factory.support)
resolveValueIfNecessary:110, BeanDefinitionValueResolver (org.springframework.beans.factory.support)
applyPropertyValues:1681, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
populateBean:1433, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) //开始处理依赖bean

doCreateBean:592, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:515, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:320, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 616881582 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$160)
getSingleton:222, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:318, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:204, AbstractBeanFactory (org.springframework.beans.factory.support) //创建bean的实例对象

invokeBeanFactoryPostProcessors:89, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:705, AbstractApplicationContext (org.springframework.context.support)
refresh:531, AbstractApplicationContext (org.springframework.context.support)
refresh:142, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:775, SpringApplication (org.springframework.boot)
refreshContext:397, SpringApplication (org.springframework.boot)
run:316, SpringApplication (org.springframework.boot)
run:1260, SpringApplication (org.springframework.boot)
run:1248, SpringApplication (org.springframework.boot)
main:58, SampleTomcatApplication (sample.tomcat) //入口:启动应用程序