查找特定包名下的注解为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-07-16 04:48:32 发布
