java 如何扫描指定包下类(包括jar中的java类)

网友投稿 994 2022-10-28


java 如何扫描指定包下类(包括jar中的java类)

在很多的实际场景中,我们需要得到某个包名下面所有的类,

包括我们自己在src里写的java类和一些第三方提供的jar包里的类,那么怎么来实现呢?

今天带大家来完成这件事。

src下面的类如何获取:

首先,比较简单的是得到我们自己写的类,我们先来完成这个,

项目的结构图如下:

我故意创建了这么个比较复杂的项目结构,现在我们就来获取com.baibin包下所有的类,并且打印他们,代码如下:

import org.junit.Test;

import java.io.File;

import java.util.ArrayList;

import java.util.List;

public class Main {

List classPaths = new ArrayList();

@Test

public void searchClass() throws ClassNotFoundException {

//包名

String basePack = "com.baibin";

//先把包名转换为路径,首先得到项目的classpath

String classpath = Main.class.getResource("/").getPath();

//然后把我们的包名basPach转换为路径名

basePack = basePack.replace(".", File.separator);

//然后把classpath和basePack合并

String searchPath = classpath + basePack;

doPath(new File(searchPath));

//这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象

for (String s : classPaths) {

//把 D:\work\code\20170401\search-class\target\classes\com\baibin\search\a\A.class 这样的绝对路径转换为全类名com.baibin.search.a.A

s = s.replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");

Class cls = Class.forName(s);

System.out.println(cls);

}

}

/**

* 该方法会得到所有的类,将类的绝对路径写入到classPaths中

* @param file

*/

private void doPath(File file) {

if (file.isDirectory()) {//文件夹

//文件夹我们就递归

File[] files = file.listFiles();

for (File f1 : files) {

doPath(f1);

}

} else {//标准文件

//标准文件我们就判断是否是class文件

if (file.getName().endsWith(".class")) {

//如果是class文件我们就放入我们的集合中。

classPaths.add(file.getPath());

}

}

}

}

效果如下:

总结:这样的src下面的都比较容易处理,也很容易想到,但是jar包下面的就没这么简单了,

但是还是有办法的。

jar中的类如何获取:

jar下的类我们可以通过JarURLConnection类来或者,代码如下:

import org.junit.Test;

import java.io.IOException;

import java.net.JarURLConnection;

import java.net.URL;

import java.util.Enumeration;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;

public class JarMain {

@Test

public void searchClass() throws IOException, ClassNotFoundException {

String basePack = "org.junit";

//通过当前线程得到类加载器从而得到URL的枚举

Enumeration urlEnumeration = Thread.currentThread().getContextClassLoader().getResources(basePack.replace(".", "/"));

while (urlEnumeration.hasMoreElements()) {

URL url = urlEnumeration.nextElement();//得到的结果大概是:jar:file:/C:/Users/ibm/.m2/repository/junit/junit/4.12/junit-4.12.jar!/org/junit

String protocol = url.getProtocol();//大概是jar

if ("jar".equalsIgnoreCase(protocol)) {

//转换为JarURLConnection

JarURLConnection connection = (JarURLConnection) url.openConnection();

if (connection != null) {

JarFile jarFile = connection.getJarFile();

if (jarFile != null) {

//得到该jar文件下面的类实体

Enumeration jarEntryEnumeration = jarFile.entries();

while (jarEntryEnumeration.hasMoreElements()) {

/*entry的结果大概是这样:

org/

org/junit/

org/junit/rules/

org/junit/runners/*/

JarEntry entry = jarEntryEnumeration.nextElement();

String jarEntryName = entry.getName();

//这里我们需要过滤不是class文件和不在basePack包名下的类

if (jarEntryName.contains(".class") && jarEntryName.replaceAll("/",".").startsWith(basePack)) {

String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replace("/", ".");

Class cls = Class.forName(className);

System.out.println(cls);

}

}

}

}

}

}

}

}

通过这两种方式我们就可以得到指定包名下面所有的类了,这个还是挺有用的,

比如spring中经常用来扫描指定包注解的实现等。

补充:获取指定包名下的所有类

写了一个工具类,用于获取指定包名下的所有类,支持递归遍历,支持注解过滤,可从 classpath (class 文件与 jar 包)中获取。

import java.io.File;

import java.io.FileFilter;

import java.lang.annotation.Annotation;

import java.net.JarURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.List;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;

public class ClassUtil {

// 获取指定包名下的所有类

public static List> getClassList(String packageName, boolean isRecursive) {

List> classList = new ArrayList>();

try {

Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replaceAll("\\.", "/"));

while (urls.hasMoreElements()) {

URL url = urls.nextElement();

if (url != null) {

String protocol = url.getProtocol();

if (protocol.equals("file")) {

String packagePath = url.getPath();

addClass(classList, packagePath, packageName, isRecursive);

} else if (protocol.equals("jar")) {

JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();

JarFile jarFile = jarURLConnection.getJarFile();

Enumeration jarEntries = jarFile.entries();

while (jarEntries.hasMoreElements()) {

JarEntry jarEntry = jarEntries.nextElement();

String jarEntryName = jarEntry.getName();

if (jarEntryName.endsWith(".class")) {

String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");

if (isRecursive || className.substring(0, className.lastIndexOf(".")).equals(packageName)) {

classList.add(Class.forName(className));

}

}

}

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

return classList;

}

// 获取指定包名下的所有类(可根据注解进行过滤)

public static List> getClassListByAnnotation(String packageName, Class extends Annotation> annotationClass) {

List> classList = new ArrayList>();

try {

Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replaceAll("\\.", "/"));

while (urls.hasMoreElements()) {

URL url = urls.nextElement();

if (url != null) {

String protocol = url.getProtocol();

if (protocol.equals("file")) {

String packagePath = url.getPath();

addClassByAnnotation(classList, packagePath, packageName, annotationClass);

} else if (protocol.equals("jar")) {

JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();

JarFile jarFile = jarURLConnection.getJarFile();

Enumeration jarEntries = jarFile.entries();

while (jarEntries.hasMoreElements()) {

JarEntry jacBblucLEsBrEntry = jarEntries.nextElement();

String jarEntryName = jarEntry.getName();

if (jarEntryName.endsWith(".class")) {

String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");

Class> cls = Class.forName(className);

if (cls.isAnnotationPresent(annotationClass)) {

classList.add(cls);

}

}

}

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

return classList;

}

private static void addClass(List> classList, String packagePath, String packageName, boolean isRecursive) {

try {

File[] files = getClassFiles(packagePath);

if (files != null) {

cBblucLEsB for (File file : files) {

String fileName = file.getName();

if (file.isFile()) {

String className = getClassName(packageName, fileName);

classList.add(Class.forName(className));

} else {

if (isRecursive) {

String subPackagePath = getSubPackagePath(packagePath, fileName);

String subPackageName = getSubPackageName(packageName, fileName);

addClass(classList, subPackagePath, subPackageName, isRecursive);

}

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

private static File[] getClassFiles(String packagePath) {

return new File(packagePath).listFiles(new FileFilter() {

@Override

public boolean accept(File file) {

return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();

}

});

}

private static String getClassName(String packageName, String fileName) {

String className = fileName.substring(0, fileName.lastIndexOf("."));

if (StringUtil.isNotEmpty(packageName)) {

className = packageName + "." + className;

}

return className;

}

private static String getSubPackagePath(String packagePath, String filePath) {

String subPackagePath = filePath;

if (StringUtil.isNotEmpty(packagePath)) {

subPackagePath = packagePath + "/" + subPackagePath;

}

return subPackagePath;

}

private static String getSubPackageName(String packageName, String filePath) {

String subPackageName = filePath;

if (StringUtil.isNotEmpty(packageName)) {

subPackageName = packageName + "." + subPackageName;

}

return subPackageName;

}

private static void addClassByAnnotation(List> classList, String packagePath, String packageName, Class extends Annotation> annotationClass) {

try {

File[] files = getClassFiles(packagePath);

if (files != null) {

for (File file : files) {

String fileName = file.getName();

if (file.isFile()) {

String className = getClassName(packageName, fileName);

Class> cls = Class.forName(className);

if (cls.isAnnotationPresent(annotationClass)) {

classList.add(cls);

}

} else {

String subPackagePath = getSubPackagePath(packagePath, fileName);

String subPackageName = getSubPackageName(packageName, fileName);

addClassByAnnotation(classList, subPackagePath, subPackageName, annotationClass);

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:svn实时同步案例!
下一篇:域名
相关文章

 发表评论

暂时没有评论,来抢沙发吧~