spring-boot源码分析之BeanFactory

前言

今天原本是打算分析beanFactory的,但由于昨天我们有一部分内容还没有分享完,所以今天就先开个倒车,把做昨天的内容先将清楚,所以今天的内容主要就是对昨天分享内容的的补充。

当然,昨天我们分享的内容beanDefinitionNames也算是BeanFactory的核心属性,所以也不能说完全没有关系:

而且从源码中我们可以看出来,beanDefinitionNamesbeanDefinitionMap这些属性的初始化大小,这也算是在学习beanFactory的相关知识吧。

BeanFactory

beanDefinitionNames内容补充

正式开始之前,我们先把昨天遗留的问题解决了。昨天,我们分享了一张beanDefinitionNames初始化的时序图,但是由于有一些内容没有梳理清楚,所以这里先做个补充。

调用过程各方法作用

SpringApplication这里就不做过多说明了,我们在前面最开始的时候就已经分析过这个类的run方法,当时也已经介绍过这个类的这些方法,他们的主要作用就是为了初始化容器,在SpringApplication的最后一个refresh方法中,最后会调用AbstractApplicationContext自身的refresh方法,这里的AbstractApplicationContextApplicationContext的抽象实现,它实现了ConfigurableApplicationContext接口(ConfigurableApplicationContext继承了ApplicationContext),我们的AnnotationConfigReactiveWebServerApplicationContext(默认容器)就是继承自它,不过并不是直接继承,它的父类继承了AbstractApplicationContext,关于容器这块的继承关系,我们改天抽个时间,专门分析下。

大部分继承了AbstractApplicationContext的容器都没有重写refresh方法,就算重写了这个方法,其内部也是调用了父类的refresh方法:

我们看下refresh的实现源码:

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

refresh方法内部,调用了很多其他方法,其中prepareRefresh的作用是为我们下面的刷新操作做准备,其内部主要是对配置的一些初始化操作:

obtainFreshBeanFactory方法的作用是刷新beanFactory,主要是对beanFactory进行一些初始化操作,如果beanFactory已经存在,会将已有的beanFactory销毁,然后重新创建,最后将beanFactory返回:

prepareBeanFactory方法的作用是对BeanFactory进行一些赋值和设置,为容器初始化操作做准备:

postProcessBeanFactory方法就是我们昨天提到的会进行包扫描的那个方法,但由于basePackagesannotatedClasses都是空,所以其中的scan方法并不会被执行。这个方法实际的作用是,后置处理BeanFactory

invokeBeanFactoryPostProcessors方法的作用是,实例化并调用所有注册的BeanFactory的后置处理器。我们昨天说的beanDefinitionNamesbeanDefinitionMap就是通过这个方法最终完成初始化的:

registerBeanPostProcessors方法和它名字一样,它的作用就是注册bean的后置处理器:

initMessageSource方法是进行消息源初始化的,主要是对web应用消息国际化提供支持的:

initApplicationEventMulticaster,这个方法是初始化spring boot应用时间广播的,如果不指定的话,默认情况下为我们指定的是SimpleApplicationEventMulticaster

onRefresh,这个方法是提供给子类初始化其他特殊bean对象的,默认实现为空,子类可根据需要重写:

registerListeners方法是用来注册事件监听器的:

finishBeanFactoryInitialization,完成beanFactory初始化,同时在方法内部会实例化剩余的单例类(不包括懒加载部分):

finishRefresh,完成刷新,主要进行一些清理、刷新、事件推送等操作:

总结

经过今天的补充之后,我相信各位小伙伴一定也对spring boot的启动和初始化过程有了更深刻的认识,因为我就是这样的感受。相比于昨天分享完内容的感受,今天我感觉整体来说要更好。一方面感觉spring boot启动和初始化的流程更清晰了,而且由于最近这几天一直在看spring boot的源码,看的多了感觉就没有那么难了,毕竟书读百遍其意自现,代码也是大同小异;另一方面在梳理分析的过程中,让我也能够清晰地看到下一步要分享的内容,明确后面地前进方向,这也算是意外的收获吧。

原文地址:https://www.cnblogs.com/caoleiCoding/p/15232227.html