最近在写一个依赖注入的小demo,碰到这么样的一个问题:
要把本项目下所有被@Component修饰的所有类注入到容器当中。
思路很简单,通过文件枚举的方式扫描出本项目的所有类文件,再对文件名进行一些小处理,就能得到本项目的所有类。
public static void scanAllClasses() {
String url = getClassPath();
List<String> classes = getClassesList(url);
// 遍历classes,如果发现@Component就注入到容器中
scanComponent2Container(classes);
}
其中,getClassPath这个方法的实现如下:
private static String getClassPath() {
String url = URLDecoder.decode(Context.class.getResource("/").getPath(), Charset.defaultCharset());
if (url.startsWith("/")) {
url = url.replaceFirst("/", "");
}
url = url.replaceAll("/", "\\\\");
return url;
}
就是通过类来取出这个类所在文件的绝对路径,并进行一些文本处理。
而getClassesList则是根据传入的类路径,通过递归进行文件枚举:
private static List<String> getClassesList(String url) {
File file = new File(url);
List<String> classes = getAllClass(file);
for (int i = 0; i < classes.size(); i++) {
classes.set(i, classes.get(i).replace(url, "").replace(".class", "").replace("\\", "."));
}
return classes;
}
递归函数:
private static List<String> getAllClass(File file) {
List<String> ret = new ArrayList<>();
if (file.isDirectory()) {
File[] list = file.listFiles();
for (var i : list) {
var j = getAllClass(i);
ret.addAll(j);
}
} else {
ret.add(file.getAbsolutePath());
}
return ret;
}
基本原理就是判断file是否为目录,如果是,继续递归,否则如果文件是class文件,加入到list,返回。
那这样,就能得到本项目下的所有类。
值得注意的是,这种方式不适用jar执行包,因为如果java直接执行jar包的话,第一步得到的类路径就是jar包的地址。
所以如果最终运行的是jar包的话,必须通过jar输入流进行读取。