Spring源码解析十四

通过前面的学习,我们已经了解了spring的初级容器是如何初始化了,但是相比于陌生的XmlBeanFactory而言ApplicationContext显然大家更加的熟悉,在spring高级容器ApplicationContext中,包含了初级容器XmlBeanFactory中所有的东西 。ApplicationContext在初级容器的基础之上,扩展了非常多的高级特性,同时也给我们提供了非常多的功能扩展点,通过这些功能扩展点,我们可以将spring这个框架的功能改造的更加满足于我实际的业务场景。从这一篇开始我们就一起去探索spring的高级容器ApplicationContext是如何初始化的吧。

我们先来看下ApplicationContext简单实用:
在这里插入图片描述可以看到,同样是解析xml文件,如果我使用ApplicationContext来解析的话,也就是将之前的XmlBeanFactory替换成了ApplicationContext的实现类CalssPathXmlApplicationContext,执行的结果和XmlBeanFactory是一样的。ApplicationContext接口的实现类也是比较多的。我们使用ClassPathXmlApplicationContext作为ApplicationContext初始化源码分析的入口。

通过ClassPathXmlApplicationContext的名称,我们可以知道它是从classpath路径加载和解析applicationContext.xml的。
我们进去ClassPathXmlApplicationContext 方法看下:
在这里插入图片描述
可以看到,在classPathXmlApplicationContextd的构造方法中,首先会把xml文件名称封装成一个String类型的数组,然后带上参数refresh的值true和parent值null,继续调用ClassPathXmlApplicationContext另外的一个重载构造方法。
我们到这个ClassPathXmlApplicationContext的重载构造方法中看下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,首先用super方法调用父类的构造器,我们层层的跟到父类AbstractApplicationContext,发现这个里面有两个方法:
我们到this() 方法中看下:
在这里插入图片描述
这里应该是初始化一个成员变量resourcePatternResolver,那getResourcePatternResolver方法能获取到什么呢?我们继续进去看下:
在这里插入图片描述
可以看到,成员变量resourcePatternResolver 被初始化了PathMatchingResourcePatternResolver类型,根据名称我们可以推测PathMatchingResourcePatternResolver应该是匹配路径的一个资源解析器,应该是获取xml文件资源的一个组件。

我们在看这个setParent方法:
在这里插入图片描述
可以看到往setParent方法中传入了参数parent,我们知道这个parent参数传入的是个null值。

我们在回到ClassPathXmlApplicationContext构造方法的位置:
在这里插入图片描述
applicationContext.xml 文件封装为String数组作为参数传入,然后调用方法setConfigLocations。
我们到这个setConfigLocactions方法中看下:
在这里插入图片描述
可以看到,在setConfigLocations方法中,通过我们传入的参数locations,构建了一个新的string数组configLocations,用于存放解析后的xml文件路径。
那这个resolvePath会怎么解析呢?我么看一下:
在这里插入图片描述
我们到方法resolveRequiredPlaceholders中看下:
在这里插入图片描述
也就是,我们传入的xml路径参数path中,如果存在占位符 ${},那方法resolveRequiredPlaceholders就可以解析占位符。而且,如果xml的路径中有${}占位符,但是却没有对应的默认属性值是会报错的。

到现在我们已经看到了,spring会为我们设置进去的xml路径进行一些准备处理,比如解析路径中的一些占位符,但是具体在什么时候加载和解析xml文件呢?
现在,我们再看ClassPathXMLApplicationContext构造方法:
在这里插入图片描述
前面我们已经看到,参数refresh的值为true,所以会调用refresh方法,那refresh方法到底是在干什呢?
我们到这个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.
			// 初始化初级容器BeanFactory,并解析xml文件
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 对spring容器beanFactory做一些准备工作
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 空实现,留个子类去拓展实现。用于注册特殊的后置处理器来加载特殊的一些bean
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 执行BeanFactory即Spring容器级别的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 在spring容器中,注册bean的后置处理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 在spring容器,初始化消息源MessageSource
				initMessageSource();

				// Initialize event multicaster for this context.
				// spring容器,初始化事件广播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 空实现,留给子类去拓展实现
				// 用于在实例化bean之前,做一些其他初始化bean的工作
				onRefresh();
			
				// Check for listener beans and register them.
				// 初始化spring容器中的各种监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 预先实例化那些非延迟加载的单例bean
				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();
			}
		}
	}

可以看到。容器ApplicationContext初始化的核心逻辑都在refresh中,下面的篇符中,我都是围绕则refresh方法来展开的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring源码解析是指对Spring框架的源代码进行深入分析和解读的过程。Spring框架是一个开源的Java企业级应用程序框架,提供了高度灵活和可扩展的开发环境。 Spring框架的源代码解析涉及了众多的模块和组件,包括核心容器、AOP(面向切面编程)、数据访问、Web开发等。通过对这些模块和组件的源代码进行解析,我们可以更加深入地了解Spring框架的工作原理和设计思想。 Spring源码解析的好处在于,可以帮助我们更好地理解Spring框架的各种功能和特性,并且能够帮助开发人员更加高效地使用和定制Spring框架,解决实际项目开发中的问题。 在进行Spring源码解析时,我们可以关注一些关键的概念和类,比如BeanFactory、ApplicationContext、BeanPostProcessor、AOP代理等。这些核心类和概念是理解Spring框架工作机制的重要基础。 进行Spring源码解析时,我们可以使用一些常见的工具和方法,比如IDE(集成开发环境)的调试功能、查看和分析源代码的注释和文档、调试和运行项目的示例代码等。 通过Spring源码解析,我们可以学到很多有关软件开发的知识和经验,比如面向对象编程、设计模式、依赖注入、控制反转等。这些知识和经验对于我们提升自己的技术水平和解决实际项目中的问题都有很大的帮助。 总之,Spring源码解析是一项非常有价值的学习和研究工作,可以帮助我们更好地理解和应用Spring框架,提高自己的技术能力和软件开发水平。希望以上的回答能够满足您的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youngerone123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值