在现在好多应用场景中,我们需要得到某个包名下面所有的类, 包括我们自己在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中的包扫描(工具)的更多相关文章

  1. java 中的包概念

    Java 中的包package, 就是电脑中的文件夹.我们平时在工作中,文件太多时,都会新建文件夹进行分类管理,java 中的包也是类似的道理,当我们的类太多时,也需要进行分类管理,这时我们就会把类文 ...

  2. Java中带包(创建及引用)的类的编译

    Java中带包(创建及引用)的类的编译与调试 java源程序的编译大家都知道,也就是cmd中到源文件所在目录下javac **.java即可,当程序中有包声明还能简简单单的直接javac **.jav ...

  3. 理解Java中【包】的概念

    Java中用package关键字定义一个包,下面通过几个实验,理解Java中的包的概念和作用. 实验1:先看一个无包的情形 在G盘下新建一个Test.java,如图1: 写下面这些代码 <spa ...

  4. java中的包以及内部类的介绍

    1:形式参数和返回值的问题(理解)    (1)形式参数:        类名:需要该类的对象        抽象类名:需要该类的子类对象        接口名:需要该接口的实现类对象    (2)返 ...

  5. java中的包有那些 ???

    java.util工具包java.sql数据库包java.io输入输出流包java.net网络包java.lang基础包这些是基本的包,还有一些其他的例如集合,反射等的工具包,你可以去查一下java ...

  6. Java中的包含义

    JAVA提供了强大的应用程序接口,既JAVA类库.他包含大量已经设计好的工具类,帮助程序员进行字符串处理.绘图.数学计算和网络应用等方面的工作.下面简单介绍JAVA核心类库中常用的组建包. 1.jav ...

  7. java中的Arrays这个工具类你真的会用吗

    Java源码系列三-工具类Arrays ​ 今天分享java的源码的第三弹,Arrays这个工具类的源码.因为近期在复习数据结构,了解到Arrays里面的排序算法和二分查找等的实现,收益匪浅,决定研读 ...

  8. Java中,包的概念、常量、静态成员、继承

    新建包:左上角-新建-包 命名规则(通常从大到小,方便整合不容易冲突)  例如:com.itnba.maya.test package必须在最顶行,之前不能再有其他代码 使用包: 快捷方式:使用包中的 ...

  9. Java中的包

    包:定义包用package关键字. 1:对类文件进行分类管理. 2:给类文件提供多层名称空间. 如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中 ...

随机推荐

  1. python的__str__()和__repr__()方法

    __str__()和__repe__()方法定义一个值通过print打印时返回时的显示样式 l=list('hello') print(l) #['h', 'e', 'l', 'l', 'o'] cl ...

  2. bzoj4861 / P3715 [BJOI2017]魔法咒语

    P3715 [BJOI2017]魔法咒语 AC自动机+dp+矩阵乘法 常规思路是按基本串建立AC自动机 然鹅这题是按禁忌串建立AC自动机 对后缀是禁忌的点以及它的失配点做上标记$(a[i].ed)$, ...

  3. com.mchange.v2.c3p0.impl.NewPooledConnection@be1839d closed by a client的正确解答

    关于c3p0在debug模式下控制台抛出的如下异常: java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE at com.mchange. ...

  4. python简说(十三)递归

    #递归就是函数自己调用自己count = 0# def abc():# pass# abc()最多循环999次

  5. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem F (Codeforces 831F) - 数论 - 暴力

    题目传送门 传送门I 传送门II 传送门III 题目大意 求一个满足$d\sum_{i = 1}^{n} \left \lceil \frac{a_i}{d} \right \rceil - \sum ...

  6. topcoder srm 335 div1

    problem1 link 直接模拟即可. import java.util.*; import java.math.*; import static java.lang.Math.*; public ...

  7. Spring 学习历程(二)

    JUnit测试 maven导入包 <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> &l ...

  8. vue学习【第五篇】:Vue组件

    什么是组件 - 每一个组件都是一个vue实例 - 每个组件均具有自身的模板template,根组件的模板就是挂载点 - 每个组件模板只能拥有一个根标签 - 子组件的数据具有作用域,以达到组件的复用 根 ...

  9. Yum自动下载RPM包及其所有依赖的包

    前几天我尝试去创建一个仅包含我们经常在 CentOS 7 下使用的软件的本地仓库.当然,我们可以使用 curl 或者 wget 下载任何软件包,然而这些命令并不能下载要求的依赖软件包.你必须去花一些时 ...

  10. R t-test cor.test

    a = c(175, 168, 168, 190, 156, 181, 182, 175, 174, 179)b = c(185, 169, 173, 173, 188, 186, 175, 174, ...