Spring是如何扫描包的 Spring5.x(源码向)
Spring是如何扫描包的 Spring5.x
锁定这个方法,Spring会在ClassPathScanningCandidateComponentProvider类的这个方法中进行扫描
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {LinkedHashSet candidates = new LinkedHashSet();try {//这是一个处理路径的步骤替换点.为/,后缀添加his.resourcePattern: "**/*.class"String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;//这里获取所有的类Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);boolean traceEnabled = this.logger.isTraceEnabled();boolean debugEnabled = this.logger.isDebugEnabled();Resource[] var7 = resources;int var8 = resources.length;//这里Spring对所有的资源进行过滤,读取文件,然后读取该类的接口,父类,父类的接口,验证有没有包含@Component注解(被作为了接口)for(int var9 = 0; var9 < var8; ++var9) {Resource resource = var7[var9];if (traceEnabled) {this.logger.trace("Scanning " + resource);}if (resource.isReadable()) {try {MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);if (this.isCandidateComponent(metadataReader)) {ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setResource(resource);sbd.setSource(resource);if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {if (debugEnabled) {this.logger.debug("Identified candidate component class: " + resource);}candidates.add(sbd);} else if (debugEnabled) {this.logger.debug("Ignored because not a concrete top-level class: " + resource);}} else if (traceEnabled) {this.logger.trace("Ignored because not matching any filter: " + resource);}} catch (Throwable var13) {throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13);}} else if (traceEnabled) {this.logger.trace("Ignored because not readable: " + resource);}}return candidates;} catch (IOException var14) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);}
}
获取所有类的步骤
修改后的路径
可以看到当前的的目录变成了/分隔的**/*.class结尾的字符串
Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
Resource是Spring定义的一种表示资源的类型,如下
package org.springframework.core.io;import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import org.springframework.lang.Nullable;public interface Resource extends InputStreamSource {boolean exists();default boolean isReadable() {return this.exists();}default boolean isOpen() {return false;}default boolean isFile() {return false;}URL getURL() throws IOException;URI getURI() throws IOException;File getFile() throws IOException;default ReadableByteChannel readableChannel() throws IOException {return Channels.newChannel(this.getInputStream());}long contentLength() throws IOException;long lastModified() throws IOException;Resource createRelative(String var1) throws IOException;@NullableString getFilename();String getDescription();
}
1.使用AbstractApplicationContext获取资源组
public Resource[] getResources(String locationPattern) throws IOException {return this.resourcePatternResolver.getResources(locationPattern);
}
2.使用ResourcePatternResolver来进一步处理,筛选路径的开头
public Resource[] getResources(String locationPattern) throws IOException {//一个检查是否为空的警报类Assert.notNull(locationPattern, "Location pattern must not be null");//因为我们是classpath开头的,所以会进入这里if (locationPattern.startsWith("classpath*:")) {return this.getPathMatcher().isPattern(locationPattern.substring("classpath*:".length())) ? this.findPathMatchingResources(locationPattern) : this.findAllClassPathResources(locationPattern.substring("classpath*:".length()));} else {int prefixEnd = locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 : locationPattern.indexOf(58) + 1;return this.getPathMatcher().isPattern(locationPattern.substring(prefixEnd)) ? this.findPathMatchingResources(locationPattern) : new Resource[]{this.getResourceLoader().getResource(locationPattern)};}
}
这里有一些似乎迷惑的操作,讲解一下
this.getPathMatcher()这里是获取了Spring的一个工具类,是一个路径匹配的工具类,
isPattern方法是为了检查该路径是否为一个path路径,如下,包含下面几种字符就被认为是path,为了安全,这样是应该的
public boolean isPattern(@Nullable String path) {if (path == null) {return false;} else {boolean uriVar = false;for(int i = 0; i < path.length(); ++i) {char c = path.charAt(i);if (c == '*' || c == '?') {return true;}if (c == '{') {uriVar = true;} else if (c == '}' && uriVar) {return true;}}return false;}
}
现在是重头戏,正式开始找类
执行this.findPathMatchingResources(locationPattern)方法
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {//对路径进行处理,保证路径的正常String rootDirPath = this.determineRootDir(locationPattern);//取一下结尾的类型信息,其实就是**/*.classString subPattern = locationPattern.substring(rootDirPath.length());//获取资源根目录,//URL [file:/E:/你的项目文件夹/target/classes/com/hhcat/hhcat/],//涉及的不是很复杂,想了解自己debug一下就行Resource[] rootDirResources = this.getResources(rootDirPath);Set<Resource> result = new LinkedHashSet(16);Resource[] var6 = rootDirResources;int var7 = rootDirResources.length;for(int var8 = 0; var8 < var7; ++var8) {Resource rootDirResource = var6[var8];Resource rootDirResource = this.resolveRootDirResource(rootDirResource);URL rootDirUrl = ((Resource)rootDirResource).getURL();if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {URL resolvedUrl = (URL)ReflectionUtils.invokeMethod(equinoxResolveMethod, (Object)null, new Object[]{rootDirUrl});if (resolvedUrl != null) {rootDirUrl = resolvedUrl;}rootDirResource = new UrlResource(rootDirUrl);}//一连串判断,是为了查看是什么类型的文件我们是file开头的if (rootDirUrl.getProtocol().startsWith("vfs")) {result.addAll(PathMatchingResourcePatternResolver.VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, this.getPathMatcher()));} //走了这里,这里是实际上的扫描包,使用了File类,扫描目录下所有的以之前那个**/*.class格式的文件,然后加入在result中,完成了扫描else if (!ResourceUtils.isJarURL(rootDirUrl) && !this.isJarResource((Resource)rootDirResource)) {result.addAll(this.doFindPathMatchingFileResources((Resource)rootDirResource, subPattern));} else {result.addAll(this.doFindPathMatchingJarResources((Resource)rootDirResource, rootDirUrl, subPattern));}}if (logger.isTraceEnabled()) {logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);}return (Resource[])result.toArray(new Resource[0]);
}
把过滤后的类返回,就完成了扫描。
Spring是如何扫描包的 Spring5.x(源码向)相关推荐
- 手撸Spring系列2:IOC/DI 思想(源码篇-IOC)
说在前头: 笔者本人为大三在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,发布的文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正. ...
- Spring5.x源码分析 | 从踩坑到放弃之环境搭建
Spring5.x源码分析--从踩坑到放弃之环境搭建 前言 自从Spring发行4.x后,很久没去好好看过Spring源码了,加上最近半年工作都是偏管理和参与设计为主,在技术细节上或多或少有点疏忽,最 ...
- Transformers包tokenizer.encode()方法源码阅读笔记
Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode
- mysql源码包和二进制包_Linux软件包(源码包和二进制包)
Linux下的软件包众多,且几乎都是经 GPL 授权.免费开源(无偿公开源代码)的.这意味着如果你具备修改软件源代码的能力,只要你愿意,可以随意修改. GPL,全称 General Public Li ...
- 微信小程序:开心锤锤超火动态表情包微信小程序源码下载自动采集
这是一款表情包小程序源码 大家刷抖音的时候应该都刷过开心锤锤这个网红卡通短视频吧 现在这一款小程序就是和它有关的 里面的表情包呢大部分都是动态表情包(斗图的时候是不是更炫) 至于里面的表情包人物的就都 ...
- 第一行代码-android-第三版-pdf扫描-思维导图-课件-源码
第一行代码-android-第三版-pdf扫描-思维导图-课件-源码 一帮公众号各种要你关注, 各种压缩包层层套娃要密码, 还要进群, 真他妈日了gou了,找了半天 分享给大家, 毫无套路! pdf扫 ...
- RPM包安装或者安装源码包
在windows下安装一个软件很轻松,只要双击.exe的文件,安装提示连续"下一步"即可,然而linux系统下安装一个软件似乎并不那么轻松了,因为我们不是在图形界面下.所以你要学会 ...
- 易启秀20150629完整包微场景制作源码,新增1.4G素材包,全新后台UI设计+采集
易启秀20150629完整包微场景制作源码,新增1.4G素材包,全新后台UI设计+采集 本文由 穷站长 于 2015-7-18 9:23 Saturday 发布在 php源码 评论(46) 最新版易启 ...
- HanLP自然语言处理包开源(包含源码)
HanLP自然语言处理包开源(包含源码) 支持中文分词(N-最短路分词.CRF分词.索引分词.用户自定义词典.词性标注),命名实体识别(中国人名.音译人名.日本人名.地名.实体机构名识别),关键词提取 ...
最新文章
- R语言list.dirs函数获取目录列表实战
- [转]Hadoop家族学习路线图
- Magic Leap大举进军AR医疗:新品率先与医疗机构合作,挖走HoloLens老客户
- spring26-2: bean的作用域
- 爬虫学习笔记(二十)—— 字体反爬
- 【mathematical statistics】2 point estimate
- 大型互联网公司架构演进之路汇总
- oracle oemrpt数据库显现
- 添加底部小火箭+目录
- 一:HTTP协议(超详解)
- C# Socket简单例子(服务器与客户端通信)
- 燕秀工具箱图库lisp_AutoCAD模具设计插件燕秀工具箱 v2.81版(64/32bit)
- 湖南职称计算机模拟试题,湖南职称计算机考试培训软件:集职称计算机考试模拟题、长沙职称计算机考试题库...
- 我为什么放弃百词斩?
- 【图论】	腾讯大战360
- 3个步骤+1个模型,「数据分析」才是「增长黑客」的核心技能
- vue中使用file-saver导出文件
- VMW配置FusionStorage Manager(FSM)虚拟机主备
- 百度搜索稳定性问题分析的故事(上)
- jQuery 流星雨特效
热门文章
- 怎么把图片变成黑白?
- Saying Good-bye to Cambridge Again --- by Xu Zhimo 再别康桥 徐志摩
- java界面分割_java将一个JFrame界面分割成多部分,每部分添加独立背景图片
- 最近收集的一些图片(第2期)
- c语言数组项目按身高排序,过三关 Java冒泡排序选择排序插入排序小练习
- 算法竞赛入门经典 第二版 习题5-5 复合词 Compound Words uva10391
- Feign 调用存在的问题
- 微信新功能,帮你用品牌成交客户!
- 京东云宙斯上传单张图片php,PHP图片上传程序(单张)
- 2023年国漫前瞻:出海、漫改剧、元宇宙