SpringBoot源码(十一): refreshContext(一)

介绍

refreshContext是springBoot启动源码中最复杂的部分了,里面的内容也非常多,将会拆分很多个章节去说。

源码

refreshContext里面就是调用AbstractApplicationContext的refresh的方法。主要的功能就是注册spring容器里面的bean,以及对bean的处理还有广播等功能。

接着看源码吧

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 1 刷新context,设置占位的propertySource
			prepareRefresh();

			// 2 获取beanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 3 设置beanFactory中相应的属性
			prepareBeanFactory(beanFactory);

			try {
				// 4 注册beanPostFactory
				postProcessBeanFactory(beanFactory);

				// 5
				invokeBeanFactoryPostProcessors(beanFactory);

				// 6
				registerBeanPostProcessors(beanFactory);

				// 7
				initMessageSource();

				// 8
				initApplicationEventMulticaster();

				// 9
				onRefresh();

				// 10
				registerListeners();

				// 11
				finishBeanFactoryInitialization(beanFactory);

				// 12
				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();
			}
		}
	}

先介绍下prepareRefresh方法

prepareRefresh

	protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
        // 设置flag
		this.closed.set(false);
		this.active.set(true);

		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}

		// 初始化之前占位的propertySource的值
		initPropertySources();

        // 验证必要的属性
		getEnvironment().validateRequiredProperties();

        // 初始化earlyApplicationEvents,后面注册applicationEvet
        // 会加入到里面去,等multicaster初始化完成之后统一发送
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

prepareRefresh方式是一些准备工作,对于之前environment中初始化占位的servletContextInitParams以及servletConfigInitParams的配置。具体可以看下StandardServletEnvironment这个类,environment初始化之前说过了。

由于有些配置例如servletContextInitParams这些必须要等到ServletContext封装可用了才可以,但是environment中封装配置是一个列表,有优先级顺序。所以为了优先级更高,必须排在前面,所以会先用StubPropertySource先占用,然后这边会替换。

接下来就是验证environment配置中有没有必填的配置,如果有必填的配置,但是值为空,则抛异常。

然后就是初始化earlyApplicationEvents ,这个主要的作用就是在multicaster还没有初始化的时候,讲事件先保存起来,等multicaster初始化完成之后,会调用(10) registerListeners统一发送事件的。

到这里prepareRefresh方法就说完了。接下来再看看obtainFreshBeanFactory方法

obtainFreshBeanFactory

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

    	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}

对于obtainFreshBeanFactory方法呢,主要作用就是设置BeanFactory的serializationId,返回beanFactory。对于serializationId的获取是获得application的id。对于application的id在上一章说过,是ContextIdApplicationContextInitializer初始化时获取spring.application.name配置的值,要是获取不到,就默认设置成application。

对于BeanFactory的获取,主要是GenericApplicationContext类在构造时候,会默认创建DefaultListableBeanFactory。对于BeanFactory后面获取bean时候会慢慢说的。

prepareBeanFactory

继续看prepareBeanFactory源码,这里主要就是对BeanFactory的一些配置了。先简单了解下,对于各种配置不可能一下子全部明白,先有个印象。

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// 设置classLoader
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// 配置BeanPostProcessor
        // ApplicationContextAwareProcessor主要是为了各种Aware使用的
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        
        // 注册特殊的依赖,在根据类型获取bean的时候用到
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// 检测ApplicationListener,并将放到Listner中
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// 注册bean
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// 手动注册environment Bean
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

prepareBeanFactory的作用就是为BeanFactory添加一些属性,以及手动注册bean。

在这里加入了classloader还有Bean转换器,以及对于各种Aware使用的BeanPostProcessor,检测为Listener的BeanPostProcessor,还有手动将environment等bean注册到容器中。

postProcessBeanFactory

这个方法是可以空方法,主要是交给子类去实现,子类去注册需要的beanPostProcessor以及bean。

比如:GenericWebApplicationContext

	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		if (this.servletContext != null) {
			beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
			beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		}
        // 注册scope到beanFactory
		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        // 注册context配置到beanFactory
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
	}

总结

这章简单介绍了refreshContext的几个步骤,主要是获取初始化的准备工作,包括替换environment的占位数据,还有设置beanFactory的serializationId,以及BeanFactory的初始化,比如添加ClassLoader,还有BeanPostProcessor,手动注册bean等。

这些都是在做一些初始化的工作。后面就会涉及到实际的调用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值