Java扫描classpath指定包路径下所有class
在写框架时 经常需要扫描classpath指定包路径下带有某个Annotation的类,自己整理了一下 封装成一个工具类了,供大家参考。
源代码
ClassPathResourceScanner.java 如下:
package com.bytebeats.jupiter.ioc;
import com.bytebeats.jupiter.util.ClassHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
/**
* ${DESCRIPTION}
*
* @author Ricky Fung
* @create 2016-12-11 16:02
*/
public class ClassPathCandidateComponentScanner {
private final Logger logger = LoggerFactory.getLogger(getClass());
public static final String CLASS_SUFFIX = ".class";
private static final Pattern INNER_PATTERN = java.util.regex.Pattern.compile("\\$(\\d+).", java.util.regex.Pattern.CASE_INSENSITIVE);
public Set<Class<?>> findCandidateComponents(String packageName) throws IOException {
if (packageName.endsWith(".")) {
packageName = packageName.substring(0, packageName.length()-1);
}
Map<String, String> classMap = new HashMap<>(32);
String path = packageName.replace(".", "/");
Enumeration<URL> urls = findAllClassPathResources(path);
while (urls!=null && urls.hasMoreElements()) {
URL url = urls.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String file = URLDecoder.decode(url.getFile(), "UTF-8");
File dir = new File(file);
if(dir.isDirectory()){
parseClassFile(dir, packageName, classMap);
}else {
throw new IllegalArgumentException("file must be directory");
}
} else if ("jar".equals(protocol)) {
parseJarFile(url, classMap);
}
}
Set<Class<?>> set = new HashSet<>(classMap.size());
for(String key : classMap.keySet()){
String className = classMap.get(key);
try {
set.add(ClassHelper.forName(className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return set;
}
protected void parseClassFile(File dir, String packageName, Map<String, String> classMap){
if(dir.isDirectory()){
File[] files = dir.listFiles();
for (File file : files) {
parseClassFile(file, packageName, classMap);
}
} else if(dir.getName().endsWith(CLASS_SUFFIX)) {
String name = dir.getPath();
name = name.substring(name.indexOf("classes")+8).replace("\\", ".");
System.out.println("file:"+dir+"\t class:"+name);
addToClassMap(name, classMap);
}
}
protected void parseJarFile(URL url, Map<String, String> classMap) throws IOException {
JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.isDirectory()) {
continue;
}
String name = entry.getName();
if(name.endsWith(CLASS_SUFFIX)){
addToClassMap(name.replace("/", "."), classMap);
}
}
}
private boolean addToClassMap(String name, Map<String, String> classMap){
if(INNER_PATTERN.matcher(name).find()){ //过滤掉匿名内部类
System.out.println("anonymous inner class:"+name);
return false;
}
System.out.println("class:"+name);
if(name.indexOf("$")>0){ //内部类
System.out.println("inner class:"+name);
}
if(!classMap.containsKey(name)){
classMap.put(name, name.substring(0, name.length()-6)); //去掉.class
}
return true;
}
protected Enumeration<URL> findAllClassPathResources(String path) throws IOException {
if(path.startsWith("/")){
path = path.substring(1);
}
Enumeration<URL> urls = ClassHelper.getClassLoader().getResources(path);
return urls;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
使用方法
ClassPathCandidateComponentScanner scanner = new ClassPathCandidateComponentScanner();
//要扫描的包名
String packageName = "com.bytebeats";
//获取该包下所有的类名称
Set<Class<?>> set = scanner.findCandidateComponents(packageName);
System.out.println(set.size());
for (Class<?> cls : set){
System.out.println(cls.getName());
}
1
2
3
4
5
6
7
8
9
这方面已经有一些不错的开源项目,例如:
reflections:https://github.com/ronmamo/reflections
Scannotation:http://scannotation.sourceforge.net/
---------------------
作者:Ricky_Fung
来源:CSDN
原文:https://blog.csdn.net/top_code/article/details/53574523
版权声明:本文为博主原创文章,转载请附上博文链接!
Java扫描classpath指定包路径下所有class的更多相关文章
- Java扫描指定文件路径下的文件并且递归扫描其子目录下的所有文件
本文主要实现了扫描指定文件路径下的文件,递归扫描其子目录下的所有文件信息,示例文件为: 要求将后缀为.dat的文件夹信息也写入到数据库中,然后将.chk文件解析,将文件中对应的内容读出来写入到数据库, ...
- WAS下获取包路径下所有类
最近做javaweb项目的混淆工作,用到proguard,该工具混淆.jar文件比较方便,故把所有项目代码和配置文件打成jar包, 生成的jar包经过proguard处理后,再次打包(解决progua ...
- Java 将数据写入全路径下的指定文件
package com.freud.algorithm.other; import java.io.File; import java.io.FileOutputStream; public clas ...
- java获取classpath以外的路径
最近在使用以前写过的代码生成器(从表名可生成所有的代码)的时候,发现生成的文件都在classpath目录下,所有的文件都得自己拷到工程目录下,于是,想优化一下,取得classpath目录以外的路径,很 ...
- <sourceDirectory>src/main/java</sourceDirectory> mvn 配置 包路径
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven ...
- java通过CLASSPATH读取包内文件
读取包内文件,使用的路径一定是相对的classpath路径,比如a,位于包内,此时可以创建读取a的字节流:InputStream in = ReadFile.class.getResourceAsSt ...
- Java递归搜索指定文件夹下的匹配文件
import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Queue; /** ...
- Spring根据包名获取包路径下的所有类
参考mybatis MapperScannerConfigurer.java 最终找到 Spring的一个类 ClassPathBeanDefinitionScanner.java 参考ClassP ...
- java.io.tmpdir指定的路径在哪?
Java.io.tmpdir介绍 System.getproperty(“java.io.tmpdir”)是获取操作系统缓存的临时目录,不同操作系统的缓存临时目录不一样, 在Windows的缓存目录为 ...
随机推荐
- 使用layui 和 jquery 问题小结
问题 1 在使用 layui 2.2.5 之前,可以引入最新版的 jquery ,使用更好的性能.也可以使用layui 的jquery内部版本.如果引入要在引入layui.js 之前引入 2 使用 s ...
- django官方文档--对静态文件的管理
一.入门级理解: 在django中对静态文件的管理和模板(template)的思路是一样的.在模板的管理中django是把app用到 到的模板都保存到app目录下的templates子目录中. 静态文 ...
- Android 版本对于 API
Android版本 API 代号 官网链接 Android 2.3.3 API 10 Gingerbread 官网 Android 3.0 API 11 Android 3.1 API 12 Andr ...
- HDU 1431 素数回文
有人问我这个问题. 个人感觉暴搜会TLE O(n*sqrt(n)).n=100000000:(推断素数用2~sqrt(n)+1 去除) 还是枚举好了. 枚举 1~10000,把他每一位存下来,回文数已 ...
- linux分区详解
点评:如果你想了解linux分区,请务必认真阅读本文.对于初学者来说,linux分区不像windows下那么一目了解. Linux 分区的规定 1. 设备管理 在 Linux 中,每一 ...
- OpenCV中图像算术操作与逻辑操作
OpenCV中图像算术操作与逻辑操作 在图像处理中有两类最重要的基础操作各自是图像点操作与块操作.简单点说图像点操作就是图像每一个像素点的相关逻辑与几何运算.块操作最常见就是基于卷积算子的各种操作.实 ...
- Machine Learning Library (MLlib) Guide, BOOKS
download.microsoft.com/download/0/9/6/096170E9-23A2.../9780735698178.pdf Microsoft Azure Essential ...
- C++11 强枚举类型
在标准C++11之前的枚举是继承C的,枚举类型不是类型安全的.枚举类型被视为整数,这使得两种不同的枚举类型之间可以进行比较. 一.C中enum类型的局限语法: enum type1{a, b, c}; ...
- Android 开发添加控件事件的三种方式
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view ...
- python将列表元素按指定数目分组
比如,有时候,我们需要将列表中的元素,按照每5个分组,分成好几个组时,可以采用下面的代码 a = [1,2,3,4,5,6,7,8,9,10,11] step = 5 b = [a[i:i+step] ...