Spring源码-ClassPathXmlApplicationContext的refresh()都做了什么?

AbstractApplicationContext的refresh方法

java 复制代码
	/**
	 * 用给定的父类创建一个新的ClassPathXmlApplicationContext
	 * Create a new ClassPathXmlApplicationContext with the given parent,
	 * 从给定的XML文件加载定义
	 * loading the definitions from the given XML files.
	 * @param configLocations 配置位置 array of resource locations 资源位置数组
	 * @param refresh whether to automatically refresh the context,是否自动刷新上下文;
	 * 加载所有bean定义并创建所有单例
	 * loading all bean definitions and creating all singletons.
	 * Alternatively, 另外 call refresh manually 手动 after further进一步 configuring the context.在进一步配置上下文之后,手动调用refresh
	 * @param parent the parent context
	 * @throws BeansException if context creation failed
	 * @see #refresh()
	 */
	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		// 调用父类构造方法,进行相关的对象创建等操作,包含属性的赋值操作
		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

接下来开始讲解这个方法内部的方法都做了什么?

prepareRefresh();

复制代码
  	/**
复制代码
		 * 前戏,做容器刷新前的准备工作
		 * 1、设置容器的启动时间
		 * 2、设置活跃状态为true
		 * 3、设置关闭状态为false
		 * 4、获取Environment对象,并加载当前系统的属性值到Environment对象中
		 * 5、准备监听器和事件的集合对象,默认为空的集合
		 */
java 复制代码
	/**
	 * 准备此上下文以进行刷新,设置其启动日期和活动标志,以及
	 * 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);
		}
        // 允许收集早期的ApplicationEvents,一旦组播器可用就发布...
		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		// 创建刷新前的监听事件集合
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

obtainFreshBeanFactory

// Tell the subclass to refresh the internal bean factory. 告诉子类刷新内部bean工厂。

// 创建容器对象:DefaultListableBeanFactory

// 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

加载xml文件生成bean定义信息就是在这里的

java 复制代码
	/**
	 * 告诉子类刷新内部bean工厂。
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance  新的BeanFactory实例
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录在当前实体的属性中
		refreshBeanFactory();
		// 返回当前实体的beanFactory属性
		return getBeanFactory();
	}

prepareBeanFactory(beanFactory)

复制代码
  	// Prepare the bean factory for use in this context.
复制代码
		// beanFactory的准备工作,对各种属性进行填充 
		prepareBeanFactory(beanFactory)
java 复制代码
/**
	 * 配置工厂的标准上下文特征
	 * Configure the factory's standard context characteristics,
	 * 比如上下文的ClassLoader和后置处理器。
	 * such as the context's ClassLoader and post-processors.
	 * @param beanFactory the BeanFactory to configure 要配置的BeanFactory
	 */
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		//  告诉内部bean工厂使用上下文的类装入器等
		// Tell the internal bean factory to use the context's class loader etc.
		// 设置beanFactory的classloader为当前context的classloader
		beanFactory.setBeanClassLoader(getClassLoader());
		// 设置beanfactory的表达式语言处理器 处理解析#{}类似这样的占位符
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		// 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具类 实体类的参数解析工具类放在spring 后续可以按需使用的
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// 添加beanPostProcessor,ApplicationContextAwareProcessor此类用来完成某些Aware对象的注入
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		// 设置要忽略自动装配的接口,很多同学理解不了为什么此处要对这些接口进行忽略,原因非常简单,这些接口的实现是由容器通过set方法进行注入的,
		// 所以在使用autowire进行注入的时候需要将这些接口进行忽略
		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.  BeanFactory接口未在普通工厂中注册为可解析类型。
		// MessageSource registered (and found for autowiring) as a bean.   MessageSource作为bean注册(并自动查找)。
		// 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入
		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.
		// 注册BPP
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// 应用程序侦听器检测器

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		// 增加对AspectJ的支持,在java中织入分为三种方式,分为编译器织入,类加载器织入,运行期织入,编译器织入是指在java编译器,采用特殊的编译器,将切面织入到java类中,
		// 而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面,运行期织入则是采用cglib和jdk进行切面的织入
		// aspectj提供了两种织入方式,第一种是通过特殊编译器,在编译器,将aspectj语言编写的切面类织入到java类中,第二种是类加载期织入,就是下面的load time weaving,此处后续讲
		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.
		// 注册默认的系统环境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());
		}
	}

postProcessBeanFactory(beanFactory);

复制代码
  		// 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的
复制代码
			postProcessBeanFactory(beanFactory);
java 复制代码
	/**
	 * 在标准初始化之后修改应用程序上下文的内部bean工厂。所有的bean定义都已加载,但还没有实例化任何bean。这允许注册特殊
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for registering special
	 * BeanPostProcessors etc in certain ApplicationContext implementations.
	 * 在标准初始化之后修改应用程序上下文的内部bean工厂。所有的bean定义都已加载,但还没有实例化任何bean。
	 * 这允许在特定的ApplicationContext实现中注册特殊的BeanPostProcessors等。
	 * @param beanFactory the bean factory used by the application context
	 */
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

invokeBeanFactoryPostProcessors

复制代码
  		// Invoke factory processors registered as beans in the context.
复制代码
			// 调用各种beanFactory处理器
			invokeBeanFactoryPostProcessors(beanFactory);
java 复制代码
	/**
	 * 实例化并且调用所有已经注册了的beanFactoryPostProcessor,遵循指明的顺序
	 *
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * 必须在单例实例化之前调用
	 * <p>Must be called before singleton instantiation.
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		// 获取到当前应用程序上下文的beanFactoryPostProcessors变量的值,并且实例化调用执行所有已经注册的beanFactoryPostProcessor
		// 默认情况下,通过getBeanFactoryPostProcessors()来获取已经注册的BFPP,但是默认是空的,那么问题来了,如果你想扩展,怎么进行扩展工作?
		// MyClassPathXmlApplicationContext 继承 ClassPathXmlApplicationContext 重写 customizeBeanFactory方法 super.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

registerBeanPostProcessors

复制代码
  		// Register bean processors that intercept bean creation.
复制代码
			// 注册bean处理器,这里只是注册功能,真正调用的是getBean方法
			registerBeanPostProcessors(beanFactory);
java 复制代码
	/**
	 * 实例化并且注册所有的beanPostProcessor
	 *
	 * Instantiate and register all BeanPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before any instantiation of application beans.
	 */
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

initMessageSource

复制代码
  		// Initialize message source for this context.
复制代码
			// 为上下文初始化message源,即不同语言的消息体,国际化处理,在springmvc的时候通过国际化的代码重点讲
			initMessageSource();
java 复制代码
	/**
	 * Initialize the MessageSource.
	 * Use parent's if none defined in this context.
	 */
	protected void initMessageSource() {
		// 获取bean工厂,一般是DefaultListableBeanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		// 首先判断是否已有xml文件定义了id为messageSource的bean对象
		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
			// 如果有,则从BeanFactory中获取这个对象
			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
			// Make MessageSource aware of parent MessageSource.
			// 当父类bean工厂不为空,并且这个bean对象是HierarchicalMessageSource类型
			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
				// 类型强制转换,转换为HierarchicalMessageSource的类型
				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
				// 判断父类的messageSource是否为空,如果等于空,则设置父类的messageSource
				if (hms.getParentMessageSource() == null) {
					// Only set parent context as parent MessageSource if no parent MessageSource
					// registered already.
					hms.setParentMessageSource(getInternalParentMessageSource());
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Using MessageSource [" + this.messageSource + "]");
			}
		}
		else {
			// Use empty MessageSource to be able to accept getMessage calls.
			// 如果没有xml文件定义信息源对象,新建DelegatingMessageSource类作为messageSource的bean
			DelegatingMessageSource dms = new DelegatingMessageSource();
			// 给这个DelegatingMessageSource添加父类消息源
			dms.setParentMessageSource(getInternalParentMessageSource());
			this.messageSource = dms;
			// 将这个messageSource实例注册到bean工厂中
			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
			}
		}
	}

initApplicationEventMulticaster

复制代码
  			// Initialize event multicaster for this context.
复制代码
			// 初始化事件监听多路广播器
			initApplicationEventMulticaster();
java 复制代码
	/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	protected void initApplicationEventMulticaster() {
		// 获取当前bean工厂,一般是DefaultListableBeanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		// 判断容器中是否存在bdName为applicationEventMulticaster的bd,也就是说自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			// 如果有,则从bean工厂得到这个bean对象
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			// 如果没有,则默认采用SimpleApplicationEventMulticaster
			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() + "]");
			}
		}
	}

onRefresh

复制代码
  		// Initialize other special beans in specific context subclasses.
复制代码
			// 留给子类来初始化其他的bean
			onRefresh();
java 复制代码
	/**
	 * 此方式是模板方法,没有添加任何实现,在springmvc中会有对应的实现
	 *
	 * Template method which can be overridden to add context-specific refresh work.
	 * Called on initialization of special beans, before instantiation of singletons.
	 * <p>This implementation is empty.
	 * @throws BeansException in case of errors
	 * @see #refresh()
	 */
	protected void onRefresh() throws BeansException {
		// For subclasses: do nothing by default.
	}

registerListeners

复制代码
  		// Check for listener beans and register them.
复制代码
			// 在所有注册的bean中查找listener bean,注册到消息广播器中
			registerListeners();
java 复制代码
	/**
	 * 注册监听器
	 *
	 * 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!
		// 从容器中获取所有实现了ApplicationListener接口的bd的bdName
		// 放入ApplicationListenerBeans集合中
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
//			getApplicationEventMulticaster().addApplicationListener(this.getBean(listenerBeanName,ApplicationListener.class));
		}

		// Publish early application events now that we finally have a multicaster...
		// 此处先发布早期的监听器集合
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

finishBeanFactoryInitialization

复制代码
  		// Instantiate all remaining (non-lazy-init) singletons.
复制代码
			// 初始化剩下的单实例(非懒加载的)
			finishBeanFactoryInitialization(beanFactory);
java 复制代码
	/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 */
	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(//后续在创建实例对象 set转换服务调getConversionService
					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.
		// 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
		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定义,说明注册的bean定义将不被修改或任何进一步的处理
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 实例化剩下的单例对象
		beanFactory.preInstantiateSingletons();
	}

finishRefresh

复制代码
  		// Last step: publish corresponding event.
复制代码
			// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
			finishRefresh();
java 复制代码
	/**
	 * 完成刷新
	 * Finish the refresh of this context, invoking the LifecycleProcessor's
	 * onRefresh() method and publishing the
	 * {@link org.springframework.context.event.ContextRefreshedEvent}.
	 */
	protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		// 清除上下文级别的资源缓存(如扫描的ASM元数据)
		// 清空在资源加载器中的所有资源缓存
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		// 为这个上下文初始化生命周期处理器
		// 初始化LifecycleProcessor.如果上下文中找到'lifecycleProcessor'的LifecycleProcessor Bean对象,
		// 则使用DefaultLifecycleProcessor
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		// 首先将刷新传播到生命周期处理器
		// 上下文刷新的通知,例如自动启动的组件
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		// 发布最终事件
		// 新建ContextRefreshedEvent事件对象,将其发布到所有监听器。
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		// 参与LiveBeansView MBean,如果是活动的
		// LiveBeansView:Sping用于支持JMX 服务的类
		// 注册当前上下文到LiveBeansView,以支持JMX服务
		LiveBeansView.registerApplicationContext(this);
	}
相关推荐
一只叫煤球的猫2 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9653 小时前
tcp/ip 中的多路复用
后端
bobz9653 小时前
tls ingress 简单记录
后端
皮皮林5514 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友4 小时前
什么是OpenSSL
后端·安全·程序员
bobz9654 小时前
mcp 直接操作浏览器
后端
前端小张同学7 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook7 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康8 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在8 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net