查找特定包名下的注解为annotationClass的class文件,本文只需要处理file和jar。
上代码。
package cn.ac.bcc.ebap.modules;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Created by zhanghaipeng on 2019/8/2.
*/
public class GetClassesWithAnnotation {
private static final Logger log = Logger.getLogger(GetClassesWithAnnotation.class);
/**
* 查找特定包名下的注解为annotationClass的class文件
* 本文只需要处理file和jar
* @param packageName 包名
* @param annotationClass 待查注解的class
* @return List<Class<?>> class集合
*/
private List<Class<?>> getClassesWithAnnotationFromPackage(String packageName, Class<? extends Annotation> annotationClass) {
List<Class<?>> classList = new ArrayList<Class<?>>();
String packageDirName = packageName.replace('.', '/');
Enumeration<URL> dirs = null;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
}
catch (IOException e) {
log.error("Failed to get resource", e);
return null;
}
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
String protocol = url.getProtocol();//file
//https://docs.oracle.com/javase/7/docs/api/java/net/URL.html
//http, https, ftp, file, and jar
//本文只需要处理file和jar
if ("file".equals(protocol) ) {
String filePath = null;
try {
filePath = URLDecoder.decode(url.getFile(), "UTF-8");
log.info ("filePath{}:"+filePath);
}
catch (UnsupportedEncodingException e) {
log.error("Failed to decode class file", e);
}
getClassesWithAnnotationFromFilePath(packageName, filePath, classList, annotationClass);
} else if ("jar".equals(protocol)) {
JarFile jar = null;
try {
jar = ((JarURLConnection) url.openConnection()).getJarFile();
//扫描jar包文件 并添加到集合中
}
catch (Exception e) {
log.error("Failed to decode class jar", e);
}
List<Class<?>> alClassList = new ArrayList<Class<?>>();
findClassesByJar(packageName, jar, alClassList);
getClassesWithAnnotationFromAllClasses(alClassList, annotationClass, classList);
}
else {
log.warn("can't process the protocol={}"+protocol);
}
}
return classList;
}
private static void findClassesByJar(String pkgName, JarFile jar, List<Class<?>> classes) {
String pkgDir = pkgName.replace(".", "/");
Enumeration<JarEntry> entry = jar.entries();
while (entry.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文
JarEntry jarEntry = entry.nextElement();
String name = jarEntry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
if (jarEntry.isDirectory() || !name.startsWith(pkgDir) || !name.endsWith(".class")) {
continue;
}
//如果是一个.class文件 而且不是目录
// 去掉后面的".class" 获取真正的类名
String className = name.substring(0, name.length() - 6);
Class<?> tempClass = loadClass(className.replace("/", "."));
// 添加到集合中去
if (tempClass != null) {
classes.add(tempClass);
}
}
}
/**
* 加载类
* @param fullClsName 类全名
* @return
*/
private static Class<?> loadClass(String fullClsName ) {
try {
return Thread.currentThread().getContextClassLoader().loadClass(fullClsName );
} catch (ClassNotFoundException e) {
log.error("PkgClsPath loadClass", e);
}
return null;
}
private void getClassesWithAnnotationFromFilePath(String packageName, String filePath, List<Class<?>> classList,
Class<? extends Annotation> annotationClass) {
Path dir = Paths.get(filePath);
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for(Path path : stream) {
String fileName = String.valueOf(path.getFileName()); // for current dir , it is 'helloworld'
//如果path是目录的话, 此处需要递归,
boolean isDir = Files.isDirectory(path);
if(isDir) {
getClassesWithAnnotationFromFilePath(packageName + "." + fileName , path.toString(), classList, annotationClass);
}
else if(fileName.endsWith (".class")) {
String className = fileName.substring(0, fileName.length() - 6);
Class<?> classes = null;
String fullClassPath = packageName + "." + className;
try {
log.info("fullClassPath={}"+fullClassPath);
// ClassLoader cl = ClassLoader.getSystemClassLoader ( );
ClassLoader cl = Thread.currentThread().getContextClassLoader();
classes = cl.loadClass (fullClassPath);
}
catch (ClassNotFoundException e) {
log.error("Failed to find class={}"+fullClassPath, e);
}
if (null != classes ) {
// log.info(classes);
Annotation a = classes.getAnnotation(annotationClass);
if(null != a){
//查看Table注解的name
try {
Method m = annotationClass.getMethod ("name", null);
Object o = m.invoke (a, null);
log.info (o);
} catch (IllegalAccessException e) {
e.printStackTrace ( );
} catch (InvocationTargetException e) {
e.printStackTrace ( );
} catch (NoSuchMethodException e) {
e.printStackTrace ( );
}
//查看Table注解的name
classList.add (classes);
}
}
}
}
}
catch (IOException e) {
log.error("Failed to read class file", e);
}
}
private void getClassesWithAnnotationFromAllClasses(List<Class<?>> inClassList,
Class<? extends Annotation> annotation, List<Class<?>> outClassList) {
for(Class<?> myClasss : inClassList) {
if (null != myClasss && null != myClasss.getAnnotation(annotation)) {
outClassList.add(myClasss);
}
}
}
public static void main(String[] args) {
GetClassesWithAnnotation getClassesWithAnnotation = new GetClassesWithAnnotation();
String packageName = "cn.ac.bcc.ebap.modules.sys.entity";
Class<? extends Annotation> annotationClass = javax.persistence.Table.class;
List<Class<?>> classes = getClassesWithAnnotation.getClassesWithAnnotationFromPackage(packageName, annotationClass);
}
}
获取特定注解的类(代码)
最新推荐文章于 2024-08-23 02:07:12 发布
该文章介绍了一种方法,通过Java反射在指定包下查找包含特定注解的class文件。主要处理file和jar协议,遍历目录和jar文件,加载类并检查是否包含目标注解。
360

被折叠的 条评论
为什么被折叠?



