在写框架时 经常需要扫描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的更多相关文章

  1. Java扫描指定文件路径下的文件并且递归扫描其子目录下的所有文件

    本文主要实现了扫描指定文件路径下的文件,递归扫描其子目录下的所有文件信息,示例文件为: 要求将后缀为.dat的文件夹信息也写入到数据库中,然后将.chk文件解析,将文件中对应的内容读出来写入到数据库, ...

  2. WAS下获取包路径下所有类

    最近做javaweb项目的混淆工作,用到proguard,该工具混淆.jar文件比较方便,故把所有项目代码和配置文件打成jar包, 生成的jar包经过proguard处理后,再次打包(解决progua ...

  3. Java 将数据写入全路径下的指定文件

    package com.freud.algorithm.other; import java.io.File; import java.io.FileOutputStream; public clas ...

  4. java获取classpath以外的路径

    最近在使用以前写过的代码生成器(从表名可生成所有的代码)的时候,发现生成的文件都在classpath目录下,所有的文件都得自己拷到工程目录下,于是,想优化一下,取得classpath目录以外的路径,很 ...

  5. <sourceDirectory>src/main/java</sourceDirectory> mvn 配置 包路径

    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven ...

  6. java通过CLASSPATH读取包内文件

    读取包内文件,使用的路径一定是相对的classpath路径,比如a,位于包内,此时可以创建读取a的字节流:InputStream in = ReadFile.class.getResourceAsSt ...

  7. Java递归搜索指定文件夹下的匹配文件

    import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Queue; /** ...

  8. Spring根据包名获取包路径下的所有类

    参考mybatis MapperScannerConfigurer.java 最终找到 Spring的一个类  ClassPathBeanDefinitionScanner.java 参考ClassP ...

  9. java.io.tmpdir指定的路径在哪?

    Java.io.tmpdir介绍 System.getproperty(“java.io.tmpdir”)是获取操作系统缓存的临时目录,不同操作系统的缓存临时目录不一样, 在Windows的缓存目录为 ...

随机推荐

  1. U811.1接口EAI系列之四--委外订单生成--VB语言

    委外订单主细表.子个构成需求.具体代码与参数说明. 下面调用的通用方法在: http://www.cnblogs.com/spring_wang/p/3393147.html 作者:王春天 2013- ...

  2. Mac office ppt无法正常输入文字的问题解决方案

     Mac office ppt无法正常输入文字的问题解决方案  Mac下每次启动office ppt后,在输入文字时会出现输入法文本框快速闪退无法正常录入文字的情况,在PowerPoint中会出现这种 ...

  3. Windows8.1远程桌面时提示凭据不工作的解决方案

    本人两台电脑都是win8.1.首先确认以下三点: 1.密码没有错 2.用户连接没有达到上线(只有我一个人尝试连) 3.该用户已开启远程连接 此时还说凭据不工作的原因是域的问题,因为mstsc默认使用M ...

  4. javaweb可部署目录结构

    webApp //项目名称 -META-INF --MANIFEST.MF -WEB-INF --classes   //编译class文件 --lib  //依赖jar --web.xml -ind ...

  5. 【Android教程】Android用户系统管理

    原文:http://android.eoe.cn/topic/android_sdk Android用户迷恋于在自己的设备上安装他们所喜欢的应用.让您的应用受用户喜欢的一种方法就是让它个性化.Andr ...

  6. [LintCode] Subarray Sum & Subarray Sum II

    Subarray Sum Given an integer array, find a subarray where the sum of numbers is zero. Your code sho ...

  7. tcp拥堵算法

    http://m.blog.csdn.net/article/details?id=6739189

  8. js判断网页是真静态还是伪静态的方法

    现在很多网站都是使用以“.html“为扩展名的网页,这样做的好处是有利于搜索引擎收录和排名,或者是其他目的,如可以缩短网址使人容易记住.不过有意思的是并不是所有的以“.html”扩展名的网页都是静态的 ...

  9. IntelliJ IDEA中的properties文件乱码转成中文[unicode码转中文]

    在IntelliJ IDEA中,一些.properties后缀的配置文件中的中文常常会是下面的样子,看不懂怎么办? 解决办法:File-->Settings-->File Encoding ...

  10. Shell获取格式化日期

    Shell获取格式化日期 shell date 获取昨天日期 使用date -d 选项: date +"%Y%m%d" -d "+n days" 今天的后n天日 ...