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的缓存目录为 ...
随机推荐
- ROC 曲线简要解释
阳性 (P, positive)阴性 (N, Negative)真阳性 (TP, true positive):正确的肯定.又称:命中 (hit)真阴性 (TN, true negative):正确的 ...
- PHP实现JS的无符号右移(>>>)
举例: JS: 5>>>2 PHP function uright($a, $n) { $c = 2147483647 >> ($n - 1); return $c &a ...
- 用Entityframework 调用Mysql时,datetime格式插入不进去数据库的解决办法。
1. 打开Model.edmx, 2. 选择userinfo中的createtime字段的属性 3. storegeneratedpattern设置值为None
- vue-router路由的使用
1.路由作用 用vue.js + vue-router创建单页面应用.页面不需要刷新就可以页面跳转,提供用户更好体验. 2.路由配置 new Router({ routes: [{ path: '/' ...
- 关于 Xcode 调试工具 GDB and LLDB
xcode 5 好像弃用了GDB .而默认使用苹果自己开发的调试工具 LLDB. http://iosre.com/forum.php?mod=viewthread&tid=52 LLD ...
- Tsk4.5异步
public async void LoadData<T>(WhereClip where,OrderByClip order) where T : Entity, new() { try ...
- 分布式缓存Memcache和Redis
引言 针对于如今计算机的CPU和网络设施,相应用程序来说,运行效率的瓶颈.已经不是代码的长度(实现同一个功能)和带宽了,而是,代码訪问资源的过程.即:让我们的程序慢下来的罪魁祸首就是IO操作. 程序从 ...
- Java 编程中关于异常处理的 10 个最佳实践
异常处理是Java 开发中的一个重要部分.它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java提供了几个异常处理特性,以try,catch 和 ...
- 每日英语:Nelson Mandela Dies at 95
Nelson Mandela, who rose from militant antiapartheid activist to become the unifying president of a ...
- 显示eclipse中Problem窗口的方法
https://blog.csdn.net/ningfuxuan/article/details/76395029 ****************************************** ...