前言:
在写代码的时候,经常会遇到一些配置包路径的代码,然后框架根据提供的包路径进行扫描,比如Spring。所以这里自己去实现一下扫描包路径下类的代码。
在看资料的过程中,总结出了两个不同的扫描方式,第一种是在扫描src下的包,这时候使用文件系统就可以获取到包下面的类文件;第二种是扫描jar包中的包路径,这时候需要使用JarURLConnection类了,这个可以将Jar包中目标包路径下的文件生成一个个JarEntity,遍历生成的JarEntitys就可以获取目标类文件。
代码实现:
public class Utils {
//从包路径下扫描
public static Set<Class>
getClasses(String packagePath) {
Set<Class> res = new HashSet<>();
String path =
packagePath.replace(".", "/");
URL url = Thread.currentThread().getContextClassLoader().getResource(path);
if (url == null) {
System.out.println(packagePath
+ "
is not exit");
return res;
}
String protocol =
url.getProtocol();
if ("jar".equalsIgnoreCase(protocol))
{
try {
res.addAll(getJarClasses(url,
packagePath));
} catch (IOException e)
{
e.printStackTrace();
return res;
}
} else if ("file".equalsIgnoreCase(protocol))
{
res.addAll(getFileClasses(url,
packagePath));
}
return res;
}
//获取file路径下的class文件
private static Set<Class>
getFileClasses(URL url, String packagePath) {
Set<Class> res = new HashSet<>();
String filePath =
url.getFile();
File dir = new File(filePath);
String[] list = dir.list();
if (list == null) return res;
for (String classPath : list) {
if (classPath.endsWith(".class")) {
classPath =
classPath.replace(".class", "");
try {
Class<?>
aClass = Class.forName(packagePath + "." + classPath);
res.add(aClass);
} catch (ClassNotFoundException
e) {
e.printStackTrace();
}
} else {
res.addAll(getClasses(packagePath
+ "."
+
classPath));
}
}
return res;
}
//使用JarURLConnection类获取路径下的所有类
private static Set<Class>
getJarClasses(URL url, String packagePath) throws IOException {
Set<Class> res = new HashSet<>();
JarURLConnection conn =
(JarURLConnection) url.openConnection();
if (conn != null) {
JarFile jarFile =
conn.getJarFile();
Enumeration<JarEntry>
entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry =
entries.nextElement();
String name =
jarEntry.getName();
if (name.contains(".class") &&
name.replaceAll("/", ".").startsWith(packagePath)) {
String className =
name.substring(0,
name.lastIndexOf(".")).replace("/", ".");
try {
Class clazz =
Class.forName(className);
res.add(clazz);
} catch (ClassNotFoundException
e) {
e.printStackTrace();
}
}
}
}
return res;
}
public static void main(String[]
args) {
Set<Class> classes =
Utils.getClasses("com.ioc");
classes.addAll(Utils.getClasses("net.sf"));
for (Class clazz : classes) {
System.out.println(clazz.getName());
}
}
}
|
这里扫描的src结构是
扫描的Jar文件是 cglib.jar