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<String> classPaths = new ArrayList<String>();
@Test
public void searchClass() throws ClassNotFoundException {
//包名
String basePack = "com.baibin";
//先把包名转换为路径,⾸先得到项⽬的classpath
String classpath = Resource("/").getPath();
//然后把我们的包名basPach转换为路径名
basePack = place(".", 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.place("/","\\").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 (Name().endsWith(".class")) {
//如果是class⽂件我们就放⼊我们的集合中。
classPaths.Path());
}
}
}
}
效果如下:
总结:这样的src下⾯的都⽐较容易处理,也很容易想到,但是jar包下⾯的就没这么简单了,
但是还是有办法的。
jar中的类如何获取:
jar下的类我们可以通过JarURLConnection类来或者,代码如下:
import org.junit.Test;
import java.io.IOException;
import java.JarURLConnection;
import java.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<URL> urlEnumeration = Thread.currentThread().getContextClassLoader().place(".", "/"));
while (urlEnumeration.hasMoreElements()) {
URL url = Element();//得到的结果⼤概是:jar:file:/C:/Users/ibm/.m2/repository/junit/junit/4.12/junit-4.12.jar!/org/junit            String protocol = Protocol();//⼤概是jar
if ("jar".equalsIgnoreCase(protocol)) {
//转换为JarURLConnection
JarURLConnection connection = (JarURLConnection) url.openConnection();
if (connection != null) {
JarFile jarFile = JarFile();
if (jarFile != null) {
//得到该jar⽂件下⾯的类实体
Enumeration<JarEntry> jarEntryEnumeration = ies();
while (jarEntryEnumeration.hasMoreElements()) {
/*entry的结果⼤概是这样:
org/
org/junit/
org/junit/rules/
org/junit/runners/*/
JarEntry entry = Element();
String jarEntryName = Name();
//这⾥我们需要过滤不是class⽂件和不在basePack包名下的类
if (ains(".class") && placeAll("/",".").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.JarURLConnection;
import java.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<Class<?>> getClassList(String packageName, boolean isRecursive) {
List<Class<?>> classList = new ArrayList<Class<?>>();
try {
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().placeAll("\\.", "/"));
while (urls.hasMoreElements()) {
URL url = Element();
if (url != null) {
String protocol = Protocol();
if (protocol.equals("file")) {
String packagePath = Path();
addClass(classList, packagePath, packageName, isRecursive);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = JarFile();
Enumeration<JarEntry> jarEntries = ies();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = Element();
String jarEntryName = Name();
if (dsWith(".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<Class<?>> getClassListByAnnotation(String packageName, Class<? extends Annotation> annotationClass) {
List<Class<?>> classList = new ArrayList<Class<?>>();
try {
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().placeAll("\\.", "/"));
spring怎么读取jar文件while (urls.hasMoreElements()) {
URL url = Element();
if (url != null) {
String protocol = Protocol();
if (protocol.equals("file")) {
String packagePath = Path();
addClassByAnnotation(classList, packagePath, packageName, annotationClass);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = JarFile();
Enumeration<JarEntry> jarEntries = ies();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = Element();
String jarEntryName = Name();
if (dsWith(".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<Class<?>> classList, String packagePath, String packageName, boolean isRecursive) {
try {
File[] files = getClassFiles(packagePath);
if (files != null) {
for (File file : files) {
String fileName = Name();
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() && Name().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<Class<?>> classList, String packagePath, String packageName, Class<? extends Annotation> annotationClass) {        try {
File[] files = getClassFiles(packagePath);
if (files != null) {
for (File file : files) {
String fileName = Name();
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();
}
}
}
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。