SpringBoot bean解析之refresh方法(一)

 bean解析是springboot IOC思想的核心, bean解析的核心则是 AbstractApplicationContext 类中的refresh方法;

可以通过SpringApplication.java的run方法——>refreshContext(context)——>refresh(context)——>AbstractApplicationContext.java的refresh方法。

    @Override
	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();
			}
		}
	}

1、prepareRefresh();

这里的context是AnnotationConfigReactiveWebServerApplicationContext类型,所以将会调用AnnotationConfigReactiveWebServerApplicationContext的prepareRefresh()方法。

	@Override
	protected void prepareRefresh() {
		this.scanner.clearCache();
		super.prepareRefresh();
	}

首先清除scanner,scanner是一个元数据的读取工厂,由于是第一次进来,没有数据缓存。

下面调用父类的prepareRefresh(),即在AbstractApplicationContext类中的方法。

	/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

设置启动时间、设置上下文为active状态。

initPropertySources是初始化属性方法

	@Override
	protected void initPropertySources() {
		ConfigurableEnvironment env = getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
		}
	}

先获得环境上下文,如果是一个web环境,就把servletContext和servletConfig属性加载到环境中。

getEnvironment().validateRequiredProperties();验证环境中是否有必备的属性,没有的话会报错。

验证环境中必备的属性如何设置?

之前的文章中曾经写到过系统初始化器,在系统初始化器中,可以设置,如:

environment.setRequiredProperties("aaa");

如果环境中没有aaa属性就会报错。

接下来会验证earlyApplicationListeners是否为空,为空的话,将applicationListeners赋给它。earlyApplicationListeners就是系统监听器。

再后面,初始化earlyApplicationEvents属性,完成prepareRefresh方法。

prepareRefresh方法完成后,会初始化bean工厂。

obtainFreshBeanFactory方法如下:

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

refreshBeanFactory()方法如下:

	@Override
	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());
	}

设置refreshed属性,表示现在进行刷新,然后为beanFactory设置序列化ID(“application”)。

getBeanFactory()返回一个DefaultListableBeanFactory的对象,是GenericApplicationContext的一个final成员变量。

发布了32 篇原创文章 · 获赞 1 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/lhf2112/article/details/104491404