在写框架时 经常需要扫描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. 转:zTree树控件key配置之title:zTree树节点名称过长如何省略显示且鼠标移入节点上能够显示全称

    当树节点的名称有些很长时,全部显示出来显得很拥挤的情况下,我们会想到用省略节点名称来代替,当鼠标移入节点时能够显示该节点的全称.这样我们应该如何做呢? 首先,我们要在树的节点内多增加一个属性用于设置该 ...

  2. PHP规范PSR0和PSR4的理解

    一.PSR0简介 下文描述了若要使用一个通用的自动加载器(autoloader),你所需要遵守的规范: 一个完全标准的命名空间(namespace)和类(class)的结构是这样的:\<Vend ...

  3. unity, unity默认的Arial字体在编译出的h5版本中不显示

    unity默认的Arial字体在编译出的h5版本中不显示.改用自己的字体可显示.

  4. 修复 dji spark 的 micro sd/tf 存储卡里不能正常播放的视频文件

    可能是因为 1.在没有正确的操作停止录像前,关掉了 spark 的电源 2.在 spark 没有完成视频存储前,关掉了 spark 的电源 总之在电脑里想查看存储卡里的视频时,发现居然无法播放,这就太 ...

  5. 【iOS XMPP】使用XMPPFramewok(五):好友列表

    转自:http://www.cnblogs.com/dyingbleed/archive/2013/05/17/3082226.html 好友列表 好友列表,在 XMPP 中被称为 roster,花名 ...

  6. LPAD在Oracle中和 mssql以及在MySQL中的不同用法 以及调用存储过程方法

    Oracle: ,') from dual ,,') from dual 效果: Mssql: )+ltrim(tt.number_no) from Tabletest as tt 效果: MySQL ...

  7. 支付宝对账单下载Java沙箱调用

    package code; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; impo ...

  8. [Windows Azure] Manage the Availability of Virtual Machines

    Manage the Availability of Virtual Machines You can ensure the availability of your application by u ...

  9. 每日英语:Political Gridlock, Beijing Style

    To admirers outside the country, China's political system stands far above the dysfunctional democra ...

  10. [整理]Unity3D游戏开发之Lua

    原文1:[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(上) 各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我地博客地址是blog.csdn.net/qinyuanpei.如果 ...