Springboot之Bean的加载过程

3,867 阅读24分钟

加载和实例化bean分以下几个重要步骤:

1、根据package扫描出需要被管理的类
2、将这些类封装成BeanDefinition并注册到BeanFactory容器
3、实例化所有扫描到的BeanDefinition,其中包括解决循环依赖、延迟加载问题

下面这张图根据Springboot启动调用链的顺序,画了这三个关键步骤被触发的时间点: 在这里插入图片描述

1、springboot怎么根据package扫描出需要被管理的类?

springboot是通过启动类上的@ComponentScan注解所指定的包路径来进行扫描的,如果没有标注这个注解,则默认从启动类所在的包路径开始扫描,会根据类的注解来判断是否需要被容器进行管理,具体代码在ConfigurationClassParser的parse方法里,从上图能看到这个方法的调用栈是SpringApplication#run()->refreshContext(context)->invokeBeanFactoryPostProcessors(beanFactory);->ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)->ConfigurationClassParser#parse,debug图如下:

下面看parse方法的代码:

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				if (bd instanceof AnnotatedBeanDefinition) {
				// parse方法里的逻辑看后面的解析,核心步骤1.1到1.8逻辑
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}
    // 核心步骤 1.9
		this.deferredImportSelectorHandler.process();
	}

parse方法会调到下面这个方法:

在这里插入图片描述

核心步骤如下:

  • 1.1:如果该类被@Component标注(即使被@Component标注的注解标注也算,比如@Configuration注解被@Component标注了,如果该类被@Configuration标注,那么也就被@Component标注),那么先处理这个类里定义的一些内部类,对这些内部类递归调用processConfigurationClass(ConfigurationClass configClass)方法,先解析内部类,再解析外层类

  • 1.2:判断是否有被@PropertySource标注,如果有这个注解,则将该注解的property配置文件里的key和value解析到Context的Environment对象里供后续使用

  • 1.3:判断是否被@ComponentScans标注(这个注解就是告知Spring容器遍历那些包路径来加载bean),根据配置的包路径来扫描所有的类,对需要被Spring容器管理的类(被@Component注解的类)会递归调用下面这个方法,知道这类上的@ComponentScans注解里指定的包路径下的所有类都被扫描并解析到Spring容器里(这里如果没有配置包路径,默认为该类所在的包路径),这个扫描是由ClassPathBeanDefinitionScanner类的doScan方法来实现的。debug图如下: 在这里插入图片描述

  • 1.4:开始解析@Import注解,这个注解可以指定某些类由Spring容器管理

  • 1.5:扫描这个类是否有被@ImportResource标注,如果有这个注解,则解析该注解,这个注解作用就是引进一xml配置,比如以前Spring项目里写了很多配置bean信息的xml文件,通过这个注解将这些bean配置文件加载进来,加载这些文件里的配置信息

  • 1.6:解析类里被@Bean标注的方法

  • 1.7:解析当前类的接口里的default方法,这里可以看出可以在接口的default方法上使用@Bean注解

  • 1.8:查看该类是否有父类和父接口,如果有的话则递归调用processConfigurationClass()方法来解析

  • 1.9:最后执行前几步中扫描出来的DeferredImportSelector类,比如我们自动加载的@EnableAutoConfiguration注解里@Import引入的用于加载自动组件的AutoConfigurationImportSelector类(原理是这个类的selectImports方法会去查看META-INF/spring.factory下找到EnableAutoConfiguration的配置里的一些自动加载的组件查找spring.factory的源码解析看这里),这个接口类放在最后执行是因为这些自动加载的类很多都用到了@Conditional相关条件注解,比如@ConditionalOnMissingBean,所以需要等到其他bean已经扫描完后再执行这个类的逻辑

1.1到1.8的代码如下:

/**
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 * multiple times as relevant sources are discovered.
	 * @param configClass the configuration class being build
	 * @param sourceClass a source class
	 * @return the superclass, or {@code null} if none found or previously processed
	 */
	@Nullable
	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {
    // 1.1
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass);
		}
    // 1.2
		// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}
    // 1.3
		// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}
    // 1.4
		// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), true);
    // 1.5
		// Process any @ImportResource annotations
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}
    // 1.6
		// Process individual @Bean methods
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}
    // 1.7
		// Process default methods on interfaces
		processInterfaces(configClass, sourceClass);
    // 1.8
		// Process superclass, if any
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

2、springboot怎么将这些类封装成BeanDefinition并注册到BeanFactory容器

通过ConfigurationClassBeanDefinitionReader来解析第三步中parser放到configurationClasses的Map里的ConfigurationClass,并解析成BeanDefinition注册到容器中,debug图如下: 在这里插入图片描述

/**
	 * Read a particular {@link ConfigurationClass}, registering bean definitions
	 * for the class itself and all of its {@link Bean} methods.
	 */
	private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    // 先判断是否有@Conditional注解,有的话,校验条件是否满足,不满足条件,则从容器中删除
		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
				this.registry.removeBeanDefinition(beanName);
			}
			this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
			return;
		}
    // 将通过@Import注解引入的类封装成beanDefinition,注册到容器内
		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		// 将通过@Bean标注的方法封装成BeanDefinition注册到容器内
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
    // 加载@ImportResource指定的配置文件里的信息,加载配置文件里的beanDefinition
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		// 执行引入的ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法,比如@EnableConfigurationProperties注解上的EnableConfigurationPropertiesRegistrar.class
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}

这里的TrackedConditionEvaluator类就是解析@Conditional注解的,比如@ConditionalOnClass、@ConditionalOnBean等注解,原理就是这些注解上都会指定一个Condition接口的实现类,通过这个类的matches方法来判断是否符合条件,比如@ConditionalOnClass注解如下图: 在这里插入图片描述

而OnClassCondition类图如下: 在这里插入图片描述

而这里有个逻辑就是像@ConditionalOnBean这个注解的条件是必须已经加载了某个bean,在调用这个注解的matches方法时,需要等到所有的bean都扫描后,所以这里还有个阶段的概念,指定当前的matches方法是在哪个阶段做匹配,比如OnBeanCondition就指定只在注册阶段匹配: 在这里插入图片描述

而这个阶段的枚举有两个: 在这里插入图片描述

PARSE_CONFIGURATION:指的是在上面的parser的parse阶段,即:在扫描包路径并封装成ConfigurationClass阶段 REGISTER_BEAN:指的就是当前这一步的reader的loadBeanDefinitionsForConfigurationClass阶段,即:将ConfigurationClass转成beanDefinition注册到容器阶段

3、springboot怎么实例化所有扫描到的BeanDefinition,其中包括解决循环依赖、延迟加载问题

而bean的真正实例化就是通过BeanFactory容器的getBean方法来实现的,先看下BeanFactory的类图: 在这里插入图片描述

这里提供了通过bean名字以及类型信息来获取bean的方法,根据开头的调用链的图,我们debug进finishBeanFactoryInitialization(beanFactory)方法的beanFactory.preInstantiateSingletons()方法里,代码如下:

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

这段代码作用就是: 1、通过getBean(beanName)方法 实例化所有非延迟加载的bean(延迟加载的bean会在给bean做注入时生成一个代理类的方法来实现)
2、遍历出所有已经实例化的SmartInitializingSingleton类,并调用这个类的afterSingletonsInstantiated()方法

getBean(beanName)源码分析:

在bean的实例化过程中,Spring将这个过程分成两个阶段:

  • 实例化阶段,Spring通过反射调用这个类的构造器得到的一个空对象,这时这个对象里的依赖都是null(除非该属性是通过构造器注入),在这个阶段完成后,就将这个空对象的引用放到一个Map中暴露出去,如果出现循环依赖时,会在这个Map中拿到引用,从而注入这个引用来解决循环依赖问题,后面会详细将这个循环依赖的解决过程,我后面称这种对象为【半实例化bean】
  • 依赖注入阶段,对空对象进行依赖注入,如果发现Spring容器内还没有所依赖的bean,则开始实例化这个所依赖的bean。我后面称这种完成注入的bean为【完全实例化bean】

核心步骤如下:

  • 检查singletonObjects这个Map(存储已经完全实例化的bean)是否存在已经存在
  • 检查earlySingletonObjects这个Map(存储提前暴露的半实例化的bean,解决循环依赖)
  • 检查singletonFactories这个Map(存储提前暴露的半实例化的bean,解决循环依赖),如果存在则将调用这个Factory的getObject方法获取bean,然后将这个bean放到earlySingletonObjects里
  • 如果上面三步中存在已经创建的bean,则检查这个bean是否是FactoryBean,是的话,则调用这个FactoryBean的getObject方法获取bean
  • 如果不存在已经创建的bean,则需要新实例化bean,首先检查是否存在非单例bean(比如scope="prototype")循环依赖问题,如果存在,则直接报错,非单例bean的循环依赖是无法解决的,因为每次都要重新new对象,每次都是一个新的引用,已经无法通过将引用提前暴露出去的方式来解决了
  • 检查是否存在父BeanFactory,如果存在,则调用父BeanFactory的getBean来进行实例化
  • 标记bean已经创建,即:在alreadyCreated这个set中加入这个bean的beanName
  • 重新合并这个beanDefinition,这个合并的意思是指如果这个bean有父bean,则需要将父bean的beanDefinition和当前这个bean的beanDefinition合并成一个BeanDefinition,比如这种定义的bean,在实例化son的时候,需要将father的beanDefinition合并到一起,因为父bean里也可能会定义一些spring的特性(比如注入一些属性等),所以需要一起实例化,否则被son继承的father里的一些注入属性会为null
  • 查看当前bean有没有被@DependsOn注解标注,该注解的意思是标注当前bean在实例化前需要依赖的其他bean,需要先实例化@DependsOn注解中指定的依赖的类
  • 检查当前bean是否是单例bean(即:只生成一个对象),单例bean走单例bean的逻辑,详见后面单例bean分析
  • 检查当前bean是否是原型bean(即:每次都生成一个新的对象),原型bean走原型bean的逻辑,详见后面分析
  • 即非单例bean也非原型bean,则走其他Scope的逻辑,详见后面分析
  • 如果最后生成的bean类型不匹配,则进行类型转换
/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 * @param name the name of the bean to retrieve
	 * @param requiredType the required type of the bean to retrieve
	 * @param args arguments to use when creating a bean instance using explicit arguments
	 * (only applied when creating a new instance as opposed to retrieving an existing one)
	 * @param typeCheckOnly whether the instance is obtained for a type check,
	 * not for actual use
	 * @return an instance of the bean
	 * @throws BeansException if the bean could not be created
	 */
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    // 获取bean的名字,这里主要会过滤FactoryBean的&符号
		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,则检查这个bean是否是FactoryBean,是的话,则调用这个FactoryBean的getObject方法获取bean
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 如果这个bean是多例模式,而多例模式循环依赖自己的话是无法解决的,因为需要无限new对象
			// 而单例模式的循环依赖是可以解决的,毕竟只有一个对象,引用只有一个,不需要无限new对象
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			// 优先使用父beanFactory实例化bean
			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);
				}
			}
      // 标记bean已经被创建
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
			try {
			  // 如果一个bean有父bean,比如<bean id="son" class="com.llf.bean.Son" parent="father" depends-on="father"></bean>,则将这个父子的链合并成一个beanDefinition,因为父bean里也可能会定义一些spring的特性,所以需要一起实例化,比如父bean里有依赖注入等
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 查看当前bean有没有被@DependsOn注解标注,该注解的意思是标注当前bean在实例化前依赖的其他bean,需要先实例化@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);
						}
					}
				}

				// 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);
				}
        // 原型模式(每次new一个新对象)的实例化
				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);
				}
        // 其他自定义Scope的实例化,比如session、request的scope的实例化
				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;
	}

3.1 单例bean的实例化

spring 默认是单例bean,即:scope="single"

核心步骤如下:

  • 检查用来存储已经创建的单例bean的Map:singletonObjects中是否存在该bean,如果存在则直接返回
  • 如果容器正在销毁,则停止创建并抛出异常
  • 将beanName放到singletonsCurrentlyInCreation这个set中,标记当前bean正在创建中
  • 调用createBean方法实例化bean,详见后面源码分析
  • 实例化完成后,从singletonsCurrentlyInCreation这个set中删除该beanName,标识该bean的创建过程已经完成(但是这个bean锁依赖的属性都没有完成注入,还不能使用)
  • 将完成实例化的bean放到singletonObjects这个Map中
  • 从singletonFactories、earlySingletonObjects缓存中删除这个bean,这两个缓存是为了解决循环依赖问题,因为已经完全实例化并已加到singletonObjects中,所以从这两个缓存中删除
  • 按实例化顺序保存到registeredSingletons这个set中( registeredSingletons是个linkedSet)
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);
}					
					
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
		  // 检查是否该单例bean已经被创建,已经被创建就直接返回
			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 + "'");
				}
				// 检查singletonsCurrentlyInCreation这个set中是否存在当前类,存在的话,说明当前类本来就处于创建过程中,则抛出错误,所以在单例bean的循环依赖场景中,如果是通过构造函数来进行注入时的循环依赖就会抛出错误,因为构造器注入的循环依赖场景会导致bean的构造过程都无法完成,只能报错(通过属性来注入时的循环依赖场景并不妨碍先new出该对象,然后再注入彼此的引用就可以了)
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
				// 调用调用这个方法时传入的函数,即: createBean(beanName, mbd, args)
					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;
					}
					// 实例化完成后,从singletonsCurrentlyInCreation这个set中删除该beanName,标识该bean的创建过程已经完成(但是这个bean锁依赖的属性都没有完成注入,还不能使用)
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
				  // 创建完成后,将bean缓存到singletonObjectsMap中,从为了解决循环依赖的几个缓存中删除提前暴露的引用(后面会详细提到)
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

createBean()方法解析:

createBean方法核心逻辑是调用doCreateBean()方法:

核心步骤如下:

  • 检查缓存FactoryBean的factoryBeanInstanceCache的Map是否存在该bean
  • 如果没有则调用createBeanInstance()来实例化对象,详见后面的createBeanInstance源码分析
  • 指向MergedBeanDefinitionPostProcessor后置处理器逻辑,这些处理器里包括负责@Resource注解解析及注入的CommonAnnotationBeanPostProcessor和负责@AutoWired及@Value注解解析和注入的AutowiredAnnotationBeanPostProcessor后置处理器
  • 将半实例化的bean(还没有注入依赖属性的bean)放到singletonFactories这个map中提前暴露出去,来解决循环依赖问题
  • 进行依赖注入操作,</a href='#populateBean'>详见后面你的源码分析
  • 检查该bean是否实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,如果实现了,则执行对应接口的set方法
  • 执行BeanPostProcessor后置处理器的postProcessBeforeInitialization方法,这个方法允许返回一个对象来替换当前的bean,比如返回一个代理
  • 执行bean的InitMethods方法,包括实现了InitializingBean接口的afterPropertiesSet方法,@Bean注解指定的init-method方法
  • 执行BeanPostProcessor后置处理器的postProcessAfterInitialization方法,这个方法允许返回一个对象来替换当前的bean,比如返回一个代理
  • 检查如果BeanPostProcessor后置处理器返回了一个新对象来代替原bean,那么提前暴露到singletonFactories这个Map中的引用就是失效的,需要将依赖当前这个bean的对象重新实例化
  • 注册bean被销毁时需要执行的方法,比如实现了DisposableBean接口的destroy方法,这个destroy方法是根据bean的scope来区分的,这个scope表明这个bean的声明周期,比如scope=request表示当前bean的生命周期持续到一次请求结束,那么在请求结束时就需要执行这个bean的destroy方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		// FactoryBean的缓存中是否存在
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
		// 实例化bean
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		//获取真正的bean
		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.
		// 执行MergedBeanDefinitionPostProcessor后置处理器,为这个bean的依赖注入做准备
		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.
		// 为了解决循环依赖,将实例化的bean的引用提前缓存到singletonFactories这个Map中,这时的bean里的依赖属性还没有被注入(通过构造器注入的属性例外),所以是不完整的
		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);
			// 执行bean的init方法(被@PostConstruct标注的方法)
			// 执行BeanPostProcessor后置处理器的方法
			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);
			}
		}
    // 如果提前暴露的bean已经被注入,这里还需要检测是否bean被重新实例化了,如果被重新实例化了,则原来暴露出去的引用已经过期,需要重新注入
		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.
		// 注册bean被销毁时需要执行的方法,比如实现了DisposableBean接口的destroy方法
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

createBeanInstance方法源码

核心逻辑如下:

  • 通过bean名称解析出bean的Class信息
  • 查看是否配置了生成对象的Supplier,如果配置了,就是用这个Supplier来生成对象
  • 检查bean是否配置了factory-method,这个就是配置一个工厂类来生成对象,比如
  • 检查是否之前已经解析过,如果已经解析过构造器或者factory-method,则不重新解析
  • 执行SmartInstantiationAwareBeanPostProcessor后置处理器的determineCandidateConstructors方法,该后置处理器返回bean的构造器,比如AutowiredAnnotationBeanPostProcessor后置处理器会返回带参数的构造器
  • 如果存在有参构造器,则执行有参构造器,并且执行过程中会负责这个构造器里参数的注入
  • 如果不存在有参构造器就执行无参构造器
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 通过bean名称解析出bean的Class信息
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}
    // 查看是否配置了生成对象的Supplier
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
    // 检查bean是否配置了factory-method,比如<bean id="myBean" factory-bean="myBeanFactory" factory-method="getMyBean"></bean>
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}
    
		// Shortcut when re-creating the same bean...
		// 检查是否之前已经解析过,如果已经解析过构造器或者factory-method,则不重新解析
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// 已经解析过则直接实例化
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		// 执行SmartInstantiationAwareBeanPostProcessor后置处理器的determineCandidateConstructors方法,该后置处理器返回bean的构造器
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
				// 执行有参数的构造器
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}
    // 执行无参构造器
		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}
	

populateBean源码分析

核心步骤如下:

  • 执行InstantiationAwareBeanPostProcessor后置处理器的postProcessAfterInstantiation方法,该方法如果返回fase则表示不需要做后续的依赖注入动作,直接返回
  • 查看当前这个BeanDefinition是否配置了依赖注入的对象
  • 根据注入类型来获取对应的需要注入的对象,默认值是0,即:没有指定是通过name还是type来注入,会使用后置处理器来完成注入,这里会通过CommonAnnotationBeanPostProcessor的postProcessProperties方法完成@Resourse的注入,通过AutowiredAnnotationBeanPostProcessor的postProcessProperties来完成@AutoWired和@Value的注入,有兴趣的同学可以看着两个方法的源码
  • 执行InstantiationAwareBeanPostProcessor后置处理器的postProcessProperties方法,这里就会执行CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor来完成相应注解的注入逻辑,同时这个方法会返回一个PropertyValues对象,如果该对象有值的话,会根据这个对象再次注入,而这两个后置处理器在处理注入时,会处理@Lazy注解标志的延迟加载逻辑,详见延迟加载源码分析 如果PropertyValues对象有值,则根据这个对象里的key找到bean里的属性,完成value的注入
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;
    // 执行InstantiationAwareBeanPostProcessor后置处理器的postProcessAfterInstantiation方法,该方法如果返回fase则表示不需要做后续的依赖注入动作,直接返回
		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;
		}
    // 查看当前这个BeanDefinition是否配置了属性
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		// 根据注入类型来获取对应的需要注入的对象,默认值是0,即:没有指定是通过name还是type来注入,会使用后置处理器来完成注入
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == 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();
			}
			//  执行InstantiationAwareBeanPostProcessor后置处理器的postProcessProperties方法,这里就会执行CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor来完成相应注解的注入逻辑,同时这个方法会返回一个PropertyValues对象,如果该对象有值的话,会根据这个对象再次注入
			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);
		}
   // 根据pvs对象来进行注入
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

延迟加载源码分析

我这里以CommonAnnotationBeanPostProcessor后置处理器的代码来分析下原理,代码位置在CommonAnnotationBeanPostProcessor类的内部类ResourceElement的getResourceToInject方法里的buildLazyResourceProxy方法,思路就是并不真正的实例化这个bean,而是返回一个代理类的引用,这个代理类里会生成一个TargetSource对象,在程序运行过程中,碰到这个bean的方法被真正调用时,就会首先调用这个TargetSource对象的getTarget方法来实例化这个bean,想看详细分析的点这里,代码如下:


protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {
		TargetSource ts = new TargetSource() {
			@Override
			public Class<?> getTargetClass() {
				return element.lookupType;
			}
			@Override
			public boolean isStatic() {
				return false;
			}
			@Override
			public Object getTarget() {
				return getResource(element, requestingBeanName);
			}
			@Override
			public void releaseTarget(Object target) {
			}
		};
		ProxyFactory pf = new ProxyFactory();
		pf.setTargetSource(ts);
		if (element.lookupType.isInterface()) {
			pf.addInterface(element.lookupType);
		}
		ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
				((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null);
		return pf.getProxy(classLoader);
	}

循环依赖问题分析

Spring只能解决单例bean的循环依赖问题,对于多例bean(scope="prototype")的是无法解决的,解决办法就是在bean半实例化出来时(这时候的bean的注入逻辑还没完成,只是刚通过反射构造器new出来的一个空对象),就将这个bean的引用提前暴露到一个Map中,而依赖这个对象的bean在创建时,会首先遍历这个Map,并将找到的引用注入到bean中,这样就解决了循环依赖问题,但是当bean循环依赖的对象是通过构造器来进行注入时,就无法解决了,因为这时候连半实例化的对象都没有(因为要通过构造器的反射来实例化对象),下面是bean在创建过程中几个缓存的get和set的时间点的分布图: 在这里插入图片描述

3.2 原型bean的创建(scope="prototype")

原型bean是每次都创建新的对象,所以每次是直接调用createBean方法,不像单例bean会将创建后的bean放到一个Map中并且每次首先查询这个Map,原型bean在创建前会调用beforePrototypeCreation()方法,将beanName放入prototypesCurrentlyInCreation这个set中,这个set存放了处于创建中的非单例bean,原型bean在创建前会遍历这个Set,如果存在则直接报错,所以对于非单例的bean的循环依赖问题,spring是没办法解决的


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

3.3 其他Scope的bean的创建

比如scope="request"、scope="session"这种生命周期的bean的创建过程,逻辑是调用通过Scope的get方法来获取bean,比如request的Scope的get方法会先从一个requestAttribute对象里取bean,如果不存在则再通过beanFactory来生成bean: 在这里插入图片描述

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