Spring IOC(二): refresh 分析 prepare過程

本文繼續跟着上一篇文章走,開始分析 AbstractApplicationrefresh 方法。

本文主要圍繞以下幾個方面進行:

加鎖

AbstractApplication 中,定義了 Object 類型的 變量 startupShutdownMonitor 作爲鎖。當執行 refresh 和 destroy 方法則會進行加鎖禁止併發操作。

synchronized (this.startupShutdownMonitor) {
   ... 
}

prepareRefresh

該方法,主要是爲refresh 方法執行 準備操作。

	protected void prepareRefresh() {
		// 設置啓動日期,closed 和 active 狀態
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
		// log 打日誌
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}
		// 初始化 一些環境變量信息,由子類實現。
		initPropertySources();
		// 驗證所有變量的合法性
		getEnvironment().validateRequiredProperties();
		// 存儲 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);
		}
		// 初始化 early ApplicationEvents 類型的事件,允許 multicaster 可用時立刻觸發。
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

以上幾步主要是初始化 資源,例如 earlyApplicationListenersapplicationListenersearlyApplicationEvents
另一方面,也會使用 initPropertySources去加載子類所需要的一些 屬性。
validateRequiredProperties 則是對屬性進行驗證。
例如,如果項目項目裏面使用了 某一個環境變量,而 對應機器或者 在 initPropertySources 加載資源未加載進去,則可以在 validateRequiredProperties 驗證不通過進行告警。

obtainFreshBeanFactory

在這裏面主要是讓子類去刷新(refresh) beanFactory。

obtainFreshBeanFactory:

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

refreshBeanFactory 是 protected 的空方法,主要看子類如何實現。

本文使用 是 AnnotationConfigApplicationContext
在這裏插入圖片描述

在 當前類 AnnotationConfigApplicationContext 中,並沒有 實現 refreshBeanFactory,而在 其父類 GenericApplication 中有實現該方法,並在 在GenericApplication 中會對 final 成員變量 beanFactory 進行初始化。默認構造爲 DefaultListableBeanFactory
GenericApplicationContextrefreshBeanFactory

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

裏面判斷了 beanFactory 初始化狀態,以及設置 了 beanFactory 的序列化id。
在這裏插入圖片描述

prepareBeanFactory

準備完環境,初始化了BeanFactory,那麼到這裏就開始要爲使用BeanFactory做準備了。

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		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);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		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()));
		}

		// Register default environment beans.
		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());
		}
	}

上文準備過程,包括添加classLoader,忽略了一些DependencyInterface(這些不需要bean初始化),還添加了兩個BeanPostProcessor

  1. ApplicationContextAwareProcessor: 用於在初始化bean時候,自動填入一些屬性。
  2. ApplicationListenerDetector: 添加ApplicationListeners 所需要的支持。

後面則根據需要提前註冊了一些bean。

覺得博主寫的有用,不妨關注博主公衆號: 六點A君。
哈哈哈,一起研究Spring:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章