java 加载class文件路径_动手实现MVC: 1. Java 扫描并加载包路径下class文件

背景

用过spring框架之后,有个指定扫描包路径,然后自动实例化一些bean,这个过程还是比较有意思的,抽象一下,即下面三个点

如何扫描包路径下所有的class文件

如何扫描jar包中对应包路径下所有的class文件

如何加载class文件

实现

目标

我们的目标是给定一个包路径,然后加载这个包路径下的所有class

考虑两种场景

包路径为依赖第三方jar包中的

包路径为自己的业务代码中的 --》 常见的一种是业务代码会编译成class文件,即扫描文件

实现

针对上面两种场景,分开说明

1. 扫描文件

实现流程比较清晰:

根据包名,获取绝对地址,直接进入包对应的目录

扫描目录下所有文件

加载所有的class文件;

如果是目录,迭代遍历目录下的class文件

加载class文件

获取包对应的绝对地址,这里先不说,下面直接给出进入目录,加载所有class文件的代码

/**

* 扫描包路径下的所有class文件

*

* @param pkgName 包名

* @param pkgPath 包对应的绝对地址

* @param classes 保存包路径下class的集合

*/

private static void findClassesByFile(String pkgName, String pkgPath, Set> classes) {

File dir = new File(pkgPath);

if (!dir.exists() || !dir.isDirectory()) {

return;

}

// 过滤获取目录,or class文件

File[] dirfiles = dir.listFiles(pathname -> pathname.isDirectory() || pathname.getName().endsWith("class"));

if (dirfiles == null || dirfiles.length == 0) {

return;

}

String className;

Class clz;

for (File f : dirfiles) {

if (f.isDirectory()) {

findClassesByFile(pkgName + "." + f.getName(),

pkgPath + "/" + f.getName(),

classes);

continue;

}

// 获取类名,干掉 ".class" 后缀

className = f.getName();

className = className.substring(0, className.length() - 6);

// 加载类

clz = loadClass(pkgName + "." + className);

if (clz != null) {

classes.add(clz);

}

}

}

2. 扫描jar

流程和上面一样,实现上稍稍有些区别,由之前的扫描文件变成遍历JarFile

/**

* 扫描包路径下的所有class文件

*

* @param pkgName 包名

* @param jar jar文件

* @param classes 保存包路径下class的集合

*/

private static void findClassesByJar(String pkgName, JarFile jar, Set> classes) {

String pkgDir = pkgName.replace(".", "/");

Enumeration entry = jar.entries();

JarEntry jarEntry;

String name, className;

Class> claze;

while (entry.hasMoreElements()) {

jarEntry = entry.nextElement();

name = jarEntry.getName();

if (name.charAt(0) == '/') {

name = name.substring(1);

}

if (jarEntry.isDirectory() || !name.startsWith(pkgDir) || !name.endsWith(".class")) {

// 非指定包路径, 非class文件

continue;

}

// 去掉后面的".class", 将路径转为package格式

className = name.substring(0, name.length() - 6);

claze = loadClass(className.replace("/", "."));

if (claze != null) {

classes.add(claze);

}

}

}

3. 扫描包

上面是具体的扫class文件的过程,那么如何根据包获取对应的jarFile or 包对应的绝对地址呢?

主要利用的是 XXX.class.getClassLoader().getResources(package), 具体如下

/**

* 扫描包路径下所有的class文件

*

* @param pkg

* @return

*/

public static Set> getClzFromPkg(String pkg) {

Set> classes = new LinkedHashSet<>();

String pkgDirName = pkg.replace('.', '/');

try {

Enumeration urls = PkgUtil.class.getClassLoader().getResources(pkgDirName);

while (urls.hasMoreElements()) {

URL url = urls.nextElement();

String protocol = url.getProtocol();

if ("file".equals(protocol)) {// 如果是以文件的形式保存在服务器上

String filePath = URLDecoder.decode(url.getFile(), "UTF-8");// 获取包的物理路径

findClassesByFile(pkg, filePath, classes);

} else if ("jar".equals(protocol)) {// 如果是jar包文件

JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();

findClassesByJar(pkg, jar, classes);

}

}

} catch (IOException e) {

e.printStackTrace();

}

return classes;

}

4. 类加载

这个还是比较简单的,一搜一大把,直接贴出

private static Class> loadClass(String fullClzName) {

try {

return Thread.currentThread().getContextClassLoader().loadClass(fullClzName);

} catch (ClassNotFoundException e) {

log.error("load class error! clz: {}, e:{}", fullClzName, e);

}

return null;

}

测试

要愉快的测试这一功能,你可以选择一个jar包,如 org.slf4j, 然后自己创建几个测试类,包名也是已 org.slf4j开头,然后调用上面的方法

Class> set = PkgUtil.getClzFromPkg("org.slf4j");

因为这个工具类我是放在 quick-mvc 工程的,所以就直接使用了我定义的包 com.hust.hui,因为没啥通用性,就给出本机测试的演示图好了

593eb11b77e80db24bf959a8c2e5fcab.gif

其他

公众号获取更多:

3d36be394b668806c51f8eea55a55ad6.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/392483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 738. 单调递增的数字(贪心算法)

给定一个非负整数 N&#xff0c;找出小于或等于 N 的最大的整数&#xff0c;同时这个整数需要满足其各个位数上的数字是单调递增。 &#xff08;当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。&#xff09; 示例 1: 输入: …

python+[:]+切片_我从C ++到Python的方式:概念上的改变

python[:]切片by asya f由asya f 我从C 到Python的方式&#xff1a;概念上的改变 (How I went from C to Python: a conceptual change) 介绍 (Introduction) People say that coding in Python is so easy that even a 6 year old can do it. This was the thought that I ha…

深度学习 免费课程_2020年排名前三的免费深度学习课程

深度学习 免费课程&#xff03;1 Fastai面向程序员的实用深度学习2020 (#1 Fastai Practical Deep Learning for Coders 2020) On 21 of August 2020, fastai released the new version of the fastai library and of their Deep Learning course!2020年8月21日&#xff0c;fas…

mysql复制主从集群搭建

近期搭了个主从复制。中间出了点小问题&#xff0c;排查搞定&#xff0c;记录下来1环境&#xff1a;虚拟机&#xff1a;OS:centos6.5Linux host2 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/LinuxserverIP192.168.18.66192.168.18.6…

java jolt tuxedo_java通过jolt调用tuxedo服务.xls

java通过jolt调用tuxedo服务.xls还剩20页未读&#xff0c;继续阅读下载文档到电脑&#xff0c;马上远离加班熬夜&#xff01;亲&#xff0c;喜欢就下载吧&#xff0c;价低环保&#xff01;内容要点&#xff1a;?private bea.jolt.pool.servlet.ServletSessionPoolManager bool…

你的周末时光是什么样的?

周末是一个特殊的假日&#xff0c;隔三差五就会有&#xff0c;来的容易去得也容易&#xff0c;即便如此&#xff0c;我们还是应该好好珍惜&#xff0c;周末可以做的事太多了&#xff0c;既可以用来减压&#xff0c;也可以为下一周的学习和工作充电&#xff0c;不管做什么&#…

leetcode 290. 单词规律(hash)

给定一种规律 pattern 和一个字符串 str &#xff0c;判断 str 是否遵循相同的规律。 这里的 遵循 指完全匹配&#xff0c;例如&#xff0c; pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。 示例1: 输入: pattern “abba”, str “dog…

2019年微博用户画像_2019年您需要了解的有关用户的信息

2019年微博用户画像by Yisroel Yakovson通过伊斯洛尔雅科夫森 2019年您需要了解的有关用户的信息 (What You Need to Know About Your Users in 2019) Users have changed a lot in the last few years. We programmers may have a culture gap to overcome in this area. If …

使用lt;jsp:includegt;,不想写死URL,动态生成URL的解决的方法

JSP中文件包括有2种方式&#xff0c;静态包括和动态包括。静态包括使用<% include file"" %>。动态包括使用<jsp:include page"" />。本文不打算介绍这2种方式的差别和使用场景&#xff0c;主要关注page和file属性的路径问题。 假设事先知道被…

java udp ip端口 设置_UDP端口扫描Java只找到1个开放的UDP端口

我对端口扫描有一个分歧.我在Java中扫描一些IP地址的UDP端口.在我的程序中(假设一切正常)我只能找到一个开放的UDP端口.在另一方面端口扫描“nmap”我得到4个开放的UDP端口.有人可以告诉我为什么我不能通过Java代码找到多个端口&#xff1f;顺便说一句,我可以在我的代码中找到真…

pandas之Seris和DataFrame

pandas是一个强大的python工具包&#xff0c;提供了大量处理数据的函数和方法&#xff0c;用于处理数据和分析数据。 使用pandas之前需要先安装pandas包&#xff0c;并通过import pandas as pd导入。 一、系列Series Seris为带标签的一维数组&#xff0c;标签即为索引。 1.Seri…

机器学习:分类_机器学习基础:K最近邻居分类

机器学习:分类In the previous stories, I had given an explanation of the program for implementation of various Regression models. Also, I had described the implementation of the Logistic Regression model. In this article, we shall see the algorithm of the K…

leetcode 714. 买卖股票的最佳时机含手续费(dp)

给定一个整数数组 prices&#xff0c;其中第 i 个元素代表了第 i 天的股票价格 &#xff1b;非负整数 fee 代表了交易股票的手续费用。 你可以无限次地完成交易&#xff0c;但是你每笔交易都需要付手续费。如果你已经购买了一个股票&#xff0c;在卖出它之前你就不能再继续购买…

如何在Angular Material中制作自定义主题

by Charlee Li通过李李 如何在Angular Material中制作自定义主题 (How to make a custom theme in Angular Material) Angular Material is a great library that implements Material Design for Angular 2. The official document is sufficient regarding the component us…

最感叹的莫过于一见如故,最悲伤的莫过于再见陌路。最深的孤独,是你明知道自己的渴望,却得对它装聋作哑。最美的你不是生如夏花,而是在时间的长河里,波澜不惊。...

最感叹的莫过于一见如故&#xff0c;最悲伤的莫过于再见陌路。最深的孤独&#xff0c;是你明知道自己的渴望&#xff0c;却得对它装聋作哑。最美的你不是生如夏花&#xff0c;而是在时间的长河里&#xff0c;波澜不惊。转载于:https://www.cnblogs.com/dj258/p/7003890.html

java vimrc_.vimrc技巧

-------------------------------------------------------------------" 设置字符编码。参考&#xff1a;http://www.rainux.org/blog/index.php/2005/10/20/106" encoding: Vim 内部使用的字符编码方式&#xff0c;包括 Vim 的buffer (缓冲区)、菜单文" 本、消…

将PDF和Gutenberg文档格式转换为文本:生产中的自然语言处理

Estimates state that 70%–85% of the world’s data is text (unstructured data). Most of the English and EU business data formats as byte text, MS Word, or Adobe PDF. [1]据估计&#xff0c;全球数据的70&#xff05;–85&#xff05;是文本(非结构化数据)。 大多数…

Go_笔试题记录-指针与值类型实现接口的区别

1、如果Add函数的调用代码为&#xff1a; func main() {var a Integer 1var b Integer 2var i interface{} &asum : i.(*Integer).Add(b)fmt.Println(sum) } 则Add函数定义正确的是&#xff08;&#xff09; A.type Integer int func (a Integer) Add(b Integer) Intege…

leetcode 48. 旋转图像

解题思路 将数组从里到外分为若干层&#xff0c; 数组 [1,2,3], [4,5,6][7,8,9]的最外层即为 [1,2,3] [4 6][7,8,9] &#xff0c;将一层分为4条边&#xff0c;如741 123&#xff0c;将741放到123的位置&#xff0c;123放到369的位置&#xff0c;如此类推&#xff08;但是放置的…

如何恢复误删的OneNote页面

今天不小心把半个月的日记删掉了&#xff01;&#xff08;为了减少页面数量&#xff0c;每个月的日记会放在同一个页面上&#xff09;。 幸运的是OneNote有自动备份功能&#xff0c;喜极而泣。 操作方法来自微软支持 打开丢失了最近笔记的笔记本。 单击“文件”>“信息”&g…