loadBeanDefinitions()
进行进一步分析 。该方法调用的是本类的一个抽象方法loadBeanDefinitions(DefaultListableBeanFactory var1)
, 此方法是模板方法,由子类具体实现:
文章插图
而 FSXAC 就是
AbstractXmlApplicationContext
的子类,所以进而分析这个类的具体实现 。文章插图
可以看到:
- 创建了 XmlBeanDefinitionReader 类,用于将 XML 文件中的 Bean 读取出来并加载 。
- 调用 XBDR 的 loadBeanDefinitions,开始启动 BeanDefinition 的加载 。
- 在具体的实现中,分别传入不同的参数 , 但是在此方法中走判断时,调用了
this.getConfigResources()
这个方法在此类中是返回的Resource[]
是 null,所以走第二个判断,获取以字符串数组 , 因为之前在 FSXAC 中就设置好了 。
文章插图
String[]
传入调用的是 XmlBeanDefinitionReader
的基类 AbstractBeanDefinitionReader
的方法:文章插图
这里就是将 String 数组中的字符串,一个一个传入调用本类重载方法,并且对其进行计数 。
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {return this.loadBeanDefinitions(location, (Set)null);}public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {// 取得 ResourceLoader,使用的是 DeaultResourceLoaderResourceLoader resourceLoader = this.getResourceLoader(); // 关键代码1if (resourceLoader == null) {//...略} else {int loadCount;// 调用 DefaultResourceLoader 的 getResource 完成具体的 Resource 定位if (!(resourceLoader instanceof ResourcePatternResolver)) { // 关键代码2Resource resource = resourceLoader.getResource(location);loadCount = this.loadBeanDefinitions((Resource)resource);//... 略} else {// 调用 DefaultResourceLoader 的 getResources 完成具体的 Resource 定位try {Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);loadCount = this.loadBeanDefinitions(resources);//... 略}//... 略}}}
可以看到最终调用的是两个参数的方法:(String location, Set<Resource> actualResources)
, 通过上面代码的简要分析,我们提取出两个重要的信息:- ResourceLoader 的作用?
- DefaultResourceLoader 的 getResource 完成了具体的 Resource 定位
而在这个 FSXAC 的例子中,这个 ResourceLoader 就是 DefaultResourceLoader,来看看是怎么具体实现
getResource()
.public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");Iterator var2 = this.protocolResolvers.iterator();Resource resource;do {if (!var2.hasNext()) {if (location.startsWith("/")) {// 处理以 / 标识的 Resource 定位return this.getResourceByPath(location);}// 处理带有 classpath 表示的 Resourceif (location.startsWith("classpath:")) {return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());}try {// 处理 URL 表示的 Resource 定位URL url = new URL(location);return new UrlResource(url);} catch (MalformedURLException var5) {// 处理既不是 classpath 也不是 URL 标识的 Resource 定位// 则将 getResource 的责任交给 getResourceByPath(),这个方法时 protected,默认实现是得到一个 ClassPathContextResource 对象,通常会由子类实现该方法 。return this.getResourceByPath(location);}}ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();resource = protocolResolver.resolve(location, this);} while(resource == null);return resource;}
通过上述分析,找到了熟悉的方法名: protected Resource getResourceByPath(String path){}
这个方法由子类 FSXAC 实现,这个方法返回的是:
FileSystemResource
对象,通过这个对象,Spring 就可以进行相关的 I/O 操作,完成 BeanDefinition 定位 。实际上这么多过程和细节,都是为了实现一个功能,对 path 进行解析,然后生成一个 FileSystemResource 对象,并返回,给 BeanDefinition 载入过程做准备 。
推荐阅读
- Shell揭秘——程序退出状态码
- 基于PL022 SPI 控制器 海思3516系列芯片SPI速率慢问题深入分析与优化
- 六部恋爱甜甜电影推荐——冬天到了 一起恋爱吧 1. 这部电影也太好看了
- 0025:2011年NOIp普及组真题——瑞士轮题解
- 4 .NET 6学习笔记——如何在.NET 6的Desktop App中使用Windows Runtime API
- 学习ASP.NET Core Blazor编程系列八——数据校验
- 1 Redis—问题
- 之四 2流高手速成记:SpringBoot整合redis及mongodb
- 自己动手写线程池——向JDK线程池进发
- 微服务组件--限流框架Spring Cloud Hystrix分析