Spring源码系列【四】——Context初始化流程(下)

2020年1月7日23:13:24 发表评论 46
摘要

Context 初始化流程

接上一篇:Spring源码系列【三】——Context初始化流程(上)

二、方法详解

2.7 #initMessageSource()

初始化消息源,消息源可用来支持消息的国际化。

/**
 * Initialize the MessageSource.
 * Use parent's if none defined in this context.
 * 初始化MessageSource
 * 如果在上下文中未定义,则使用父项
 */
protected void initMessageSource() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
                // 如果在配置中已经配置了messageSource,那么将messageSource提取并记录在this.messageSource中
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
		// Make MessageSource aware of parent MessageSource.
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				// Only set parent context as parent MessageSource if no parent MessageSource
				// registered already.
				// 如果尚未注册父MessageSource,则仅将父上下文设置为父MessageSource
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Using MessageSource [" + this.messageSource + "]");
		}
	}
	else {
		// Use empty MessageSource to be able to accept getMessage calls.
		// 使用空的MessageSource可以接受getMessage调用(如果用户并没有定义配置文件,那么使用临时的DelegatingMessageSource以便于作为调用getMessage方法返回)
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms;
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
		}
	}
}

可以查看 MessageSource.java 接口:用于解析消息的策略界面,支持参数化以及此类信息的国际化。

如图getMessage():

Spring源码系列【四】——Context初始化流程(下)

大致意思就是,通过读取并将自定义资源文件配置记录在容器中,那么就可以在获取资源文件的时候使用了,例如在 AbstractApplicationContext 中的获取资源文件属性的方法就是:

return getMessageSource().getMessage(code, args, locale);

 

2.8 #initApplicationEventMulticaster()

初始化应用事件广播器。事件广播器用来向 ApplicationListener 通知各种应用产生的事件,是标准的观察者模式。

/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * 初始化ApplicationEventMulticaster
 * 如果上下文中未定义,则使用SimpleApplicationEventMulticaster
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
		}
	}
	else {
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
					"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
		}
	}
}

初始化广播器逻辑考虑两种情况:如果用户自定义了事件广播器,就使用自定义的事件广播器,如果用户没有定义,则使用默认的 ApplicationEventMulticaster。其中 new SimpleApplicationEventMulticaster(beanFactory); 就是默认广播器的实现。

 

2.9 #onRefresh()

该方法是留给子类的扩展步骤,用来让特定的 Context 子类初始化其他的 Bean。

/**
 * Template method which can be overridden to add context-specific refresh work.
 * Called on initialization of special beans, before instantiation of singletons.
 * 可以重写的模版方法以添加特定于上下文的刷新操作
 * 在所有单例bean初始化之前调用
 * <p>This implementation is empty.
 * @throws BeansException in case of errors
 * @see #refresh()
 */
protected void onRefresh() throws BeansException {
	// For subclasses: do nothing by default.
}

 

2.10 #registerListeners()

把实现了ApplicationListener 的 Bean 注册到事件广播器,并对广播器中的早期未广播事件进行通知。

/**
 * Add beans that implement ApplicationListener as listeners.
 * Doesn't affect other listeners, which can be added without being beans.
 */
protected void registerListeners() {
	// Register statically specified listeners first.
	// 首先注册静态指定的监听器
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let post-processors apply to them!
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// Publish early application events now that we finally have a multicaster...
	// 至此拥有了一个广播器,可以发布早起的应用程序事件
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

 

2.11 #finishBeanFactoryInitialization()

完成 BeanFactory 的初始化工作,其中包括 ConversionService 的设置、配置冻结以及非延迟加载的 bean 的初始化工作。

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 * 完成此上下文的BeanFactory的初始化
 * 初始化所有剩余的单例bean
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// Initialize conversion service for this context.
	// 为此上下文初始化转换服务
	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 bean post-processor
	// (such as a PropertyPlaceholderConfigurer bean) registered any before:
	// at this point, primarily for resolution in annotation attribute values.
	// 如果没有bean后处理器,则注册默认的嵌入式值解析器(例如PropertyPlaceholderConfigurer bean)之前注册过的任何东西:
	// 主要用于注释属性值的解析。
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	}

	// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
	// 尽早初始化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();
}

 

2.12 #finishRefresh()

完成上下文的 refresh 工作,调用 LifecycleProcessor 的 onFresh() 方法,以及发布 ContextRefreshEvent 事件。

/**
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 * 完成此上下文的刷新,调用LifecycleProcessor的onRefresh()方法并发布
 */
protected void finishRefresh() {
	// Clear context-level resource caches (such as ASM metadata from scanning).
	// 清除上下文级别的资源缓存,例如来自扫描的ASM元数据
	clearResourceCaches();

	// Initialize lifecycle processor for this context.
	// 为此上下文初始化生命周期处理器
	initLifecycleProcessor();

	// Propagate refresh to lifecycle processor first.
	// 首先将刷新传播到生命周期处理器
	getLifecycleProcessor().onRefresh();

	// Publish the final event.
	// 发布最终事件
	publishEvent(new ContextRefreshedEvent(this));

	// Participate in LiveBeansView MBean, if active.
	// 如果是活动的,则加入到LiveBeansView MBean
	LiveBeansView.registerApplicationContext(this);
}

Spring 中提供了 Lifecycle 接口,该接口中包含 start 和 stop 方法,实现此接口后 Spring 会保证在启动的时候调用 start 方法开始生命周期,并在 Spring 关闭的时候调用 stop 方法来结束生命周期,通常用于配置后台程序,在启动后一直运行(比如对 MQ 进行轮询等)。ApplicationContext 的初始化最后正是保证了这一功能的实现。

  • initLifecycleProcessor

当 ApplicationContext 启动或停止时,它会通过 LifecycleProcessor 来与所有声明的 bean 的周期做状态更新,而在 LifecycleProcessor 使用之前需要初始化。

  • onRefresh

启动所有实现了 Lifecycle 接口的bean。

  • publishEvent

当完成 ApplicationContext 初始化的时候,要通过 Spring 中的事件发布机制发出 ContextRefreshedEvent 事件,以保证对应的监听器可以做进一步的逻辑处理。

 

2.13 #resetCommonCaches()

在 finally 中重置公共的缓存,比如 ReflectionUtils 中的缓存、AnnotationUtils 中的缓存。

/**
 * Reset Spring's common reflection metadata caches, in particular the
 * {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType}
 * and {@link CachedIntrospectionResults} caches.
 * @since 4.2
 * @see ReflectionUtils#clearCache()
 * @see AnnotationUtils#clearCache()
 * @see ResolvableType#clearCache()
 * @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
 */
protected void resetCommonCaches() {
	ReflectionUtils.clearCache();
	AnnotationUtils.clearCache();
	ResolvableType.clearCache();
	CachedIntrospectionResults.clearClassLoader(getClassLoader());
}

 

三、Context初始化流程思维导图

至此,以上为代码、注释及说明,简明扼要的用思维导图概括如下图:

Spring源码系列【四】——Context初始化流程(下)

 

(本文完)

  • 我的微信
  • 微信扫一扫
  • weinxin
  • 微信公众号
  • 微信公众号(习惯沉淀)
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: