包扫描
1.包扫描过程
包扫描事实上就是通过包名称来扫描到该包下该包下的文件夹下的所有class文件,为我们需要处理的.class文件提前提供一个获取.class文件的一个手段。
只需要提供该包的名称便可以扫描到包下所有的.class文件。而事实上包相当于文件夹。
那我们需要做的就是对提供的包名称进行处理,从而做一个工具可以自动扫描到该包下的所有类。
First :
通过包名称得到URL,再根据URL判断该包属于普通包还是jar
Second:
若是普通包,我们需要去做判断,分两种情况
1.该包下直接就是子文件(.class文件)
2.该包下存在子文件夹,那么我们又得将这个文件夹看做是普通包对待,接着判断属于哪两种情况。
其实在这一步采用的是递归的方法,之前对递归也不是很熟练,不知道在什么时候用敌对,对于这一步来是个很好的例子,一个很好的方法理解 ==递归 就是只考虑本层需要干的事情。
对于普通包来说我们最终的目的是要扫描出clas是文件,但此时阻挡我们的是给的包名称可能包含的不是class文件而是一个或多个文件夹,这些文件夹中可能含有class文件,就是一环套一环的感觉。
那我给一个方法就是dealDirectory( String rootName, File curFile).那这个方法来处理普通包,可以看做是我们本层所要分析及实现的,那本层我们需要干的事情就是判断是上述说的两种情况,因为对一个包名称来说无非两种情况,dealDirectory(String rootName, File curFile)需要干的事情就是做两种判断,当curFile文件下是文件夹是调用自己(也就是dealDirectory(),因为此时的文件夹又可以看做时候一个普通包),当curFile文件下是class文件时,直接当做文件处理。
Third :
若是jar包,只有判断出是class文件我们当做文件处理,其他的不做处理
2.代码
public abstract class PackageScanner {
public PackageScanner() {
}
public abstract void dealClass(Class<?> className);
private void dealFile(String rootName, File curFile) {
String fileName = curFile.getName();
if (fileName.endsWith(".class")) {
fileName = fileName.replace(".class", "");
try {
Class<?> klass = Class.forName(rootName + "." + fileName);
dealClass(klass);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void dealDirectory(String rootName, File curFile) {
//得到当前curFile中是否含有子文件夹或者文件列表
File[] fileList = curFile.listFiles();
for(File file : fileList) {
if (file.isDirectory()) {
dealDirectory("rootName" + file.getName(), file);
} else if(file.isFile()){
dealFile(rootName, file);
}
}
}
private void dealJarPackage(URL url) {
try {
JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile jarFile = connection.getJarFile();
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jar = jarEntries.nextElement();
if(jar.isDirectory() || !jar.getName().endsWith(".class")) {
continue;
}
String jarName = jar.getName();
jarName = jarName.replace(".class", "");
jarName = jarName.replace("/", ".");
try {
Class<?> klass = Class.forName(jarName);
dealClass(klass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void scannPackege(String packegeName) {
String rootName = packegeName;
//可以通过将XX.xx.xx转化为xx/xx/xx/
//转化为xx/xx/xx/的目的地为了准确得到统一定位url,再通过url判断是file还是jar
packegeName = packegeName.replace(".", "/");
URL url = Thread.currentThread().getContextClassLoader().getResource(packegeName);
if (url.getProtocol().equals("file")) {
//处理普通包
try {
URI uri = url.toURI();
File root = new File(uri);
//root是得到当前packegeName的绝对路径
dealDirectory(rootName, root);
} catch (Exception e) {
e.printStackTrace();
}
} else {
//处理jar包
dealJarPackage(url);
}
}
}
```