spring源码之源码之单例bean的创建流程

单例bean是什么

用人话讲就是你无论在哪调用这个bean注入这个bean,都是同一个bean。
因此需要确保其线程安全。这通常通过无状态设计、同步机制或线程局部变量等方式实现

在哪开始创建Bean?

在刷新容器的时候,在刷新完成的前一步 (finishBeanFactoryInitialization方法) 创建Bean(非懒加载的单例bean)
今天就从finishBeanFactoryInitialization(beanFactory)作为入口看看bean是怎么创建的。

容器刷新的步骤

  1. 准备刷新:就是设置一下容器状态,加载一些基本环境和初始化事件监听器之类的。(初始化容器)
  2. 准备一个新的bean工厂:其实就是获取到构造上下文时创建的Bean工厂。(对于可重复刷新的则是销毁并重新new一个Bean工厂)(获取bean工厂)
  3. 为bean工厂做准备:设置类加载器、表达式解析器、属性编辑器、配置后置处理器、忽略一些依赖注入的接口等等。简单理解为(初始化bean工厂)
  4. 后处理 Bean 工厂:就是一个扩展点,他本身没有实现,需要子类进行实现。
  5. 调用 Bean 工厂后置处理器:调用所有注册的 BeanFactoryPostProcessor,允许它们对 BeanDefinition 进行修改或扩展。
  6. 册bean的后置处理器:将所有的Bean后置处理器注册到Bean工厂中,以便在Bean的创建和初始化过程中进行调用
  7. 初始化消息源:设置国际化消息源,用于支持多语言环境。
  8. 初始化事件广播器:用于发布和监听应用事件
  9. onRefresh():一个扩展点,springboot内置tomcat就是在这里启动的
  10. 注册监听器:从 Bean 工厂中获取所有实现了 ApplicationListener 接口的 Bean
  11. 实例化所有非懒加载的单例bean
  12. 完成刷新:清理缓存,并执行一些刷新后的操作

开始执行finishBeanFactoryInitialization

最后一行就是开始创建单例bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		//检查容器中是否存在名为 conversionService 的 Bean,并且该 Bean 的类型是否为 ConversionService。如果存在,则将其设置为容器的默认转换服务。
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		//检查容器是否已经注册了嵌入式值解析器
		//用于解析字符串中的占位符(如 ${xxx.x})
		if (!beanFactory.hasEmbeddedValueResolver()) {
			//如果没有注册,则注册一个默认的嵌入式值解析器。
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		//获取所有实现了 LoadTimeWeaverAware 接口的 Bean 的名称
		//获取所有需要提前初始化的 LoadTimeWeaverAware Bean。
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		//停止使用临时的类加载器,可能为了提高性能避免资源泄露等等
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		//冻结 Bean 定义的配置,不再允许修改
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		//实例化剩下的单例bean
		beanFactory.preInstantiateSingletons();
	}

开始执行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...
		//遍历beanName,创建非懒加载的单例bean
		for (String beanName : beanNames) {
			//合并Bean的定义
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//判断bean不是抽象类     是单例bean          不是延迟加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//判断Bean是不是工厂bean
				if (isFactoryBean(beanName)) {
					//获取工厂bean需要在名字前加一个前缀 &
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					//判断是否需要立即初始化工厂 Bean 创建的 Bean
					if (bean instanceof FactoryBean) {
						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());
						}
						//工厂bean会优先实例化自己,如果实现了SmartFactoryBean接口就会立即调用getObject实例化bean
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					//普通Bean ,获取bean
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		//后置处理
		for (String beanName : beanNames) {
			//在单例池里拿到单例bean
			Object singletonInstance = getSingleton(beanName);
			//判断单例bean是否实现了SmartInitializingSingleton接口
			//如果实现了统一调用afterSingletonsInstantiated方法(在所有单例bean实例化后调用)

			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {

					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}
  1. 为什么要合并Bean定义?
    在父子bean中,如果不合并 Bean 的定义,可能会导致 Bean 的配置不完整或错误
  2. 工厂bean在前面文章讲bean工厂时有讲过,FactoryBean 是一种特殊的 Bean,它本身是一个工厂,负责创建其他 Bean 的实例

开始执行getBean(beanName),doGetBean(),

getBean简单理解:如果是单例就从单例池获取bean,如果单例池没有就创建并放到单例池。如果不是单例就创建一个。
也就是说创建bean就是在获取bean的逻辑里面。有就直接拿,没有就创建。

	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	//按照获取bean的逻辑看,获取不到再创建
	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//获取一个标准的beanName(如果传过来的是一个别名会转化为标准的名字)
		String beanName = transformedBeanName(name);
		Object beanInstance;

		// Eagerly check singleton cache for manually registered singletons.
		//获取单例Bean(从单例池中获取)
		//如果是多例bean在这就拿不到直接走else的逻辑
		Object sharedInstance = getSingleton(beanName);
		//如果存在就证明是单例bean,否则走else逻辑
		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创建的bean或者普通单例bean
			//比如beanName前面有个&就是获取工厂bean本身
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			//进入这里说明没有拿到单例bean(意味着单例bean没被创建)或者说不是单例bean
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			//如果bean在创建中就会抛异常
			//如果Bean正在创建中,可能出现了循环依赖,需要抛出异常
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			//获取父工厂
			BeanFactory parentBeanFactory = getParentBeanFactory();
			//如果它有父工厂并且 当前BeanFactory中没有找到Bean定义可以尝试从父BeanFactory中查找
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				//转为标准名字,因为可能是别名
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
				//检查父BeanFactory是否是AbstractBeanFactory类型。如果是直接doGetBean委托父工厂去查找或创建
					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) {
				//如果父工厂不是AbstractBeanFactory类型,并且指定了Bean的类型(requiredType),调用父工厂的getBean方法,并传入Bean类型
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
				//如果父工厂不是AbstractBeanFactory类型,并且没有传入构造参数或指定类型,直接调用父工厂的getBean方法
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
				//核心了 开始尝试创建Bean
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}
				//合并Bean定义
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				//检查bena定义
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				//优先创建当前bean所依赖的bean。
				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.
				//判断是否为单例bean
				if (mbd.isSingleton()) {
					//从单例池中获取单例Bean,如果不存在则创建
					//注意,getSingleton里还有一个功能单例bean保存到单例池
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//如果getSingleton方法里查找不到这个单例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;
						}
					});
					//获取工厂bean本身或者工厂bean创建的bean或者普通单例bean
			//比如beanName前面有个&就是获取工厂bean本身
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				//先是从单例池尝试获取,单例池肯定获取不到多例bean,所以必然会到这里来
				//如果是多例bean
				else if (mbd.isPrototype()) {
					//多例Bean每次请求都会创建一个新的实例。
					// 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);
	}

补充

  1. 核心的createBean在上一篇文章讲了,这篇文章讲的是从容器刷新开始讲的。
  2. 注释也是我自己写的,有查资料,本人也是一边学一边写的,如有错误请指正。
  3. 关键也是部署源码跑debug,spring 或 spring boot都行,然后不同版本可能逻辑不太一样,但是大差不差
  4. 我一开始也是在源码东点一下西点一下最后都不知道去哪了,挺头大的。最后我的方法就是不要太在意每个环节里面具体怎么实现的,先搞清楚有哪些东西分别有什么用,有哪些步骤和启动流程,最后再挨个研究。

你可能感兴趣的:(spring源码,spring,java,后端)