当前位置: 首页 > news >正文

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

在这里插入图片描述

AbstractApplicationContext的refresh方法

	/*** 用给定的父类创建一个新的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、准备监听器和事件的集合对象,默认为空的集合*/
	/*** 准备此上下文以进行刷新,设置其启动日期和活动标志,以及* 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定义信息就是在这里的

	/*** 告诉子类刷新内部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)
/*** 配置工厂的标准上下文特征* 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的classloaderbeanFactory.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.// 注册BPPbeanFactory.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);
	/*** 在标准初始化之后修改应用程序上下文的内部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);
	/*** 实例化并且调用所有已经注册了的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);
	/*** 实例化并且注册所有的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();
	/*** Initialize the MessageSource.* Use parent's if none defined in this context.*/protected void initMessageSource() {// 获取bean工厂,一般是DefaultListableBeanFactoryConfigurableListableBeanFactory 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是否为空,如果等于空,则设置父类的messageSourceif (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的beanDelegatingMessageSource 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();
	/*** Initialize the ApplicationEventMulticaster.* Uses SimpleApplicationEventMulticaster if none defined in the context.* @see org.springframework.context.event.SimpleApplicationEventMulticaster*/protected void initApplicationEventMulticaster() {// 获取当前bean工厂,一般是DefaultListableBeanFactoryConfigurableListableBeanFactory 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 {// 如果没有,则默认采用SimpleApplicationEventMulticasterthis.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.
			// 留给子类来初始化其他的beanonRefresh();
/*** 此方式是模板方法,没有添加任何实现,在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();
	/*** 注册监听器** 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);
/*** 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转换服务调getConversionServicebeanFactory.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();
	/*** 完成刷新* 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对象,// 则使用DefaultLifecycleProcessorinitLifecycleProcessor();// 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);}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 无缝编码体验:在PyCharm中高效使用远程文件编辑功能
  • 竞赛报名管理系统asp.net+sqlserver
  • python链接harbor,查询项目,镜像,版本
  • 虚拟机如何使用pxe服务实现自动安装系统
  • 【深度学习实战(52)】混淆矩阵计算
  • HCIE-Datacom题库__填空题
  • 基于Orangepi全志H616学习Python3
  • ValueListenableBuilder 和 addListener 在 ChangeNotifier的区别
  • 基于LoRA和AdaLoRA微调Qwen1.5-0.5B-Chat
  • 每日一练 | Day 4
  • 逆向API接口加解密技术解析归纳
  • sais复杂推理能力评估笔记(一):baseline简介
  • 《亿级流量系统架构设计与实战》第二章 通用的高并发架构设计
  • jmeter 重试机制
  • 抽象代数精解【5】
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • Create React App 使用
  • Git同步原始仓库到Fork仓库中
  • java概述
  • oschina
  • Selenium实战教程系列(二)---元素定位
  • Zepto.js源码学习之二
  • 动态魔术使用DBMS_SQL
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 前端工程化(Gulp、Webpack)-webpack
  • 前端学习笔记之观察者模式
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 用简单代码看卷积组块发展
  • 在weex里面使用chart图表
  • 中文输入法与React文本输入框的问题与解决方案
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​2020 年大前端技术趋势解读
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #Datawhale AI夏令营第4期#AIGC文生图方向复盘
  • (差分)胡桃爱原石
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .Net Core 微服务之Consul(三)-KV存储分布式锁
  • .NET 快速重构概要1
  • .NET 中的轻量级线程安全
  • .NET微信公众号开发-2.0创建自定义菜单
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • /boot 内存空间不够
  • @Async注解的坑,小心
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [000-01-022].第06节:RabbitMQ中的交换机介绍
  • [15] 使用Opencv_CUDA 模块实现基本计算机视觉程序
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标
  • [AutoSar]BSW_OS 01 priority ceiling protocol(PCP)