Java中的包扫描(工具)
在现在好多应用场景中,我们需要得到某个包名下面所有的类, 包括我们自己在src里写的java类和一些第三方提供的jar包里的类,那么怎么来实现呢?
今天带大家来完成这件事。
先分享代码:
1.这个类是一个抽象类,对类的处理交给用户,所以就有了dealClass的抽象方法。
package com.mec.packscanner.core; import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile; public abstract class PackageScanner {
public PackageScanner() {} public abstract void dealClass(Class<?> klass); //扫描一般的包。
private void scanPackage(String packageName,File currentfile) {
File[] filelist = currentfile.listFiles(new FileFilter() {
//FileFilter是文件过滤器,源代码只写了一个accapt的抽象方法。
@Override
public boolean accept(File pathName) {
if(pathName.isDirectory()) { //判断是否是目录
return true;
}
return pathName.getName().endsWith(".class");
}
}); for(File file:filelist) {
if(file.isDirectory()) {
scanPackage(packageName + "." + file.getName(),file);
}else {
String fileName = file.getName().replace(".class", "");
String className = packageName + "." + fileName;
try {
Class<?> klass = Class.forName(className);//取出所有的类
if(klass.isAnnotation() //不扫描注解类、枚举类、接口和八大基本类型。
||klass.isEnum()
||klass.isInterface()
||klass.isPrimitive()) {
continue;
}
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
} //扫描jar包方法。
private void scanPackage(URL url) throws IOException {
JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
JarFile jarfile = urlConnection.getJarFile();
Enumeration<JarEntry> jarEntries = jarfile.entries();
while(jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarName = jarEntry.getName();
if(!jarName.endsWith(".class")) {
continue;
}
String className = jarName.replace(".class", "").replaceAll("/", "."); try {
Class<?> klass = Class.forName(className);
if (klass.isAnnotation()
|| klass.isInterface()
|| klass.isEnum()
|| klass.isPrimitive()) {
continue;
}
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} //用类名扫描
public void packageScan(Class<?> klass) {
packageScan(klass.getPackage().getName());
} //用包名进行扫描
public void packageScan(String packageName) {
String packOpperPath = packageName.replace(".","/"); //线程上下文类加载器得到当前的classpath的绝对路径.(动态加载资源)
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
try {
//(Thread.currentThread().getContextClassLoader().getResource(""))
//(来得到当前的classpath的绝对路径的URI表示法。)
Enumeration<URL> resources = classloader.getResources(packOpperPath);
while(resources.hasMoreElements()) {
//先获得本类的所在位置
URL url = resources.nextElement(); //url.getProtocol()是获取URL的HTTP协议。
if(url.getProtocol().equals("jar")) {
//判断是不是jar包
scanPackage(url);
}else {
//此方法不会自动将链接中的非法字符转义。
//而在File转化成URI的时候,会将链接中的特殊字符如#或!等字符进行编码。
File file = new File(url.toURI());
if(!file.exists()) {
continue;
}
scanPackage(packageName,file);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
这个是抽象类,对于扫描,我们只提供扫描的工具,而定义抽象方法是往外接,通过使用者的使用来决定用类名还是包名。
对于jar包的扫描,可以进JarURLConnection类和JarFile类的源码中可以理解。


2.定义测试类,它是扫描jar包的:

package com.mec.packscanner.test;
import com.mec.packscanner.core.PackageScanner;
public class Test {
public static void main(String[] args) {
new PackageScanner() {
@Override
public void dealClass(Class<?> klass) {
System.out.println(klass.getName());
}
}.packageScan("com.mec.xml_view.core");;
}
}
结果:

从结果我们可以看出把jar包中的每一个class都输出了,匿名内部类都被扫描出来了。
我们来看看普通包的结果吧:

package com.mec.packscanner.test;
import com.mec.packscanner.core.PackageScanner;
public class Test {
public static void main(String[] args) {
new PackageScanner() {
@Override
public void dealClass(Class<?> klass) {
System.out.println(klass.getName());
}
}.packageScan("com.mec.server_client.core");;
}
}

对普通的包也是,这个例子除了接口,其他的都被扫描出来了。
若有漏洞,请指正!感谢您的阅读。
Java中的包扫描(工具)的更多相关文章
- java 中的包概念
Java 中的包package, 就是电脑中的文件夹.我们平时在工作中,文件太多时,都会新建文件夹进行分类管理,java 中的包也是类似的道理,当我们的类太多时,也需要进行分类管理,这时我们就会把类文 ...
- Java中带包(创建及引用)的类的编译
Java中带包(创建及引用)的类的编译与调试 java源程序的编译大家都知道,也就是cmd中到源文件所在目录下javac **.java即可,当程序中有包声明还能简简单单的直接javac **.jav ...
- 理解Java中【包】的概念
Java中用package关键字定义一个包,下面通过几个实验,理解Java中的包的概念和作用. 实验1:先看一个无包的情形 在G盘下新建一个Test.java,如图1: 写下面这些代码 <spa ...
- java中的包以及内部类的介绍
1:形式参数和返回值的问题(理解) (1)形式参数: 类名:需要该类的对象 抽象类名:需要该类的子类对象 接口名:需要该接口的实现类对象 (2)返 ...
- java中的包有那些 ???
java.util工具包java.sql数据库包java.io输入输出流包java.net网络包java.lang基础包这些是基本的包,还有一些其他的例如集合,反射等的工具包,你可以去查一下java ...
- Java中的包含义
JAVA提供了强大的应用程序接口,既JAVA类库.他包含大量已经设计好的工具类,帮助程序员进行字符串处理.绘图.数学计算和网络应用等方面的工作.下面简单介绍JAVA核心类库中常用的组建包. 1.jav ...
- java中的Arrays这个工具类你真的会用吗
Java源码系列三-工具类Arrays 今天分享java的源码的第三弹,Arrays这个工具类的源码.因为近期在复习数据结构,了解到Arrays里面的排序算法和二分查找等的实现,收益匪浅,决定研读 ...
- Java中,包的概念、常量、静态成员、继承
新建包:左上角-新建-包 命名规则(通常从大到小,方便整合不容易冲突) 例如:com.itnba.maya.test package必须在最顶行,之前不能再有其他代码 使用包: 快捷方式:使用包中的 ...
- Java中的包
包:定义包用package关键字. 1:对类文件进行分类管理. 2:给类文件提供多层名称空间. 如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中 ...
随机推荐
- django模板继承
可以将每个html公共的部分做成一个基本模板,其他模板继承这个基本模板,则会拥有基本模板的所有内容. views.py from django.shortcuts import render def ...
- bzoj2716/2648 / P4169 [Violet]天使玩偶/SJY摆棋子
P4169 [Violet]天使玩偶/SJY摆棋子 k-d tree 模板 找了好几天才发现输出优化错了....真是zz...... 当子树非常不平衡时,就用替罪羊树的思想,拍扁重建. luogu有个 ...
- 被fancybox坑的心路历程
今天项目中需要使用fancybox来展示图片,但是使用中发现fancybox没起作用,点击图片直接刷新了页面! fancybox的原理是通过给a标签绑定事件,使得a标签不在是直接跳转链接,而是把链接中 ...
- javadoc中{@link}与@see的简单使用以及区别
因为公司的测试直接对着java api进行外部服务的测试,故最近对javadoc的要求从0变成了严重依赖,有些时候在javadoc不得不引用其他class,以便更加清晰的说明上下文以及含义,发现指向别 ...
- The Usage of Lambda and Heap in the C++ STL
The Usage of Lambda and Heap in the C++ STL Heap In c++ STL, the heap had been implemented as the pr ...
- Java排序算法之选择排序
一.算法原理 简单选择排序的基本思想:给定数组:int[] arr={里面n个数据}:第1趟排序,在待排序数据arr[1]~arr[n-1]中选出最小的数据,将它与arrr[0]交换:第2趟,在待排序 ...
- Received empty response from Zabbix Agent at[172.16.1.51]. Assuming that agent dropped connection because of access permissions
Centos7.5 Zabbix创建主机ZBX爆红 原因:/etc/zabbix/zabbix_agentd.conf配置文件的Server写错了 解决方法: [root@db01 ~]# vim / ...
- python --- 08 文件操作
一. 文件 f = open(文件路径,mode = '模式',encoding = '编码格式') 1.基础 ① 读写时,主要看光标的位置 ②操作完成要写 f.close( ) f.flu ...
- topcoder srm 450 div1
problem1 link 用$f[i][0],f[i][1]$表示从$i$位置开始Alice是先手是否可以胜利,是后手是否可以胜利. problem2link 每次钱数够$price$时可以选择使得 ...
- Python3基础 list reverse 反转列表
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...