一个实用的处理类,主要实现的功能是:自动扫描指定包下的所有类,可以设置是否扫描内部类、是否递归扫描子包、自定义过滤规则等等,下面介绍基本用法及其代码:
一、方法说明
1 2 3 4 5 6 7 8 9 10 |
// 无参构造器,默认是排除内部类、并搜索符合规则 ClassPathScanHandler handler =new ClassPathScanHandler(); // 创建一个扫描处理器,排除内部类 扫描符合条件的类 ClassPathScanHandler handler = new ClassPathScanHandler(true, true, classFilters); //递归扫描包:org.apache.commons.io 下符合自定义过滤规则的类 Set<Class<?>> calssList = handler.getPackageAllClasses( "org.apache.commons.io", true); |
二、参数说明
- boolean excludeInner:该参数表示是否排除内部类,true->是 false->否,默认=true
- boolean checkInOrEx:该参数表示过滤规则适用情况,true—>搜索符合规则的 false->排除符合规则的,默认=true
- List<String> classFilters:自定义过滤规则,如果是null或者空,即全部符合不过滤,默认为null。过滤规则可以自定义为:Xyz或Xyz*或*Xyz或*Xyz*等类似的格式
- Set<Class<?>> getPackageAllClasses(String basePackage,boolean recursive);参数 basePackage:标识扫描的基包 ; 参数:recursive:标识是否递归扫描子包
三、处理类代码
ClassPathScanHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
package michael.utils; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Pattern; import org.apache.log4j.Logger; /** * 扫描指定包(包括jar)下的class文件 <br> * http://www.micmiu.com * @author michael */ public class ClassPathScanHandler { /** * logger */ private static final Logger logger = Logger .getLogger(ClassPathScanHandler.class); /** * 是否排除内部类 true->是 false->否 */ private boolean excludeInner = true; /** * 过滤规则适用情况 true—>搜索符合规则的 false->排除符合规则的 */ private boolean checkInOrEx = true; /** * 过滤规则列表 如果是null或者空,即全部符合不过滤 */ private List<String> classFilters = null; /** * 无参构造器,默认是排除内部类、并搜索符合规则 */ public ClassPathScanHandler() { } /** * excludeInner:是否排除内部类 true->是 false->否<br> * checkInOrEx:过滤规则适用情况 true—>搜索符合规则的 false->排除符合规则的<br> * classFilters:自定义过滤规则,如果是null或者空,即全部符合不过滤 * @param excludeInner * @param checkInOrEx * @param classFilters */ public ClassPathScanHandler(Boolean excludeInner, Boolean checkInOrEx, List<String> classFilters) { this.excludeInner = excludeInner; this.checkInOrEx = checkInOrEx; this.classFilters = classFilters; } /** * 扫描包 * @param basePackage 基础包 * @param recursive 是否递归搜索子包 * @return Set */ public Set<Class<?>> getPackageAllClasses(String basePackage, boolean recursive) { Set<Class<?>> classes = new LinkedHashSet<Class<?>>(); String packageName = basePackage; if (packageName.endsWith(".")) { packageName = packageName .substring(0, packageName.lastIndexOf('.')); } String package2Path = packageName.replace('.', '/'); Enumeration<URL> dirs; try { dirs = Thread.currentThread().getContextClassLoader().getResources( package2Path); while (dirs.hasMoreElements()) { URL url = dirs.nextElement(); String protocol = url.getProtocol(); if ("file".equals(protocol)) { logger.info("扫描file类型的class文件...."); String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); doScanPackageClassesByFile(classes, packageName, filePath, recursive); } else if ("jar".equals(protocol)) { logger.info("扫描jar文件中的类...."); doScanPackageClassesByJar(packageName, url, recursive, classes); } } } catch (IOException e) { logger.error("IOException error:", e); } return classes; } /** * 以jar的方式扫描包下的所有Class文件<br> * @param basePackage eg:michael.utils. * @param url * @param recursive * @param classes */ private void doScanPackageClassesByJar(String basePackage, URL url, final boolean recursive, Set<Class<?>> classes) { String packageName = basePackage; String package2Path = packageName.replace('.', '/'); JarFile jar; try { jar = ((JarURLConnection) url.openConnection()).getJarFile(); Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); if (!name.startsWith(package2Path) || entry.isDirectory()) { continue; } // 判断是否递归搜索子包 if (!recursive && name.lastIndexOf('/') != package2Path.length()) { continue; } // 判断是否过滤 inner class if (this.excludeInner && name.indexOf('$') != -1) { logger.info("exclude inner class with name:" + name); continue; } String classSimpleName = name .substring(name.lastIndexOf('/') + 1); // 判定是否符合过滤条件 if (this.filterClassName(classSimpleName)) { String className = name.replace('/', '.'); className = className.substring(0, className.length() - 6); try { classes.add(Thread.currentThread() .getContextClassLoader().loadClass(className)); } catch (ClassNotFoundException e) { logger.error("Class.forName error:", e); } } } } catch (IOException e) { logger.error("IOException error:", e); } } /** * 以文件的方式扫描包下的所有Class文件 * * @param packageName * @param packagePath * @param recursive * @param classes */ private void doScanPackageClassesByFile(Set<Class<?>> classes, String packageName, String packagePath, boolean recursive) { File dir = new File(packagePath); if (!dir.exists() || !dir.isDirectory()) { return; } final boolean fileRecursive = recursive; File[] dirfiles = dir.listFiles(new FileFilter() { // 自定义文件过滤规则 public boolean accept(File file) { if (file.isDirectory()) { return fileRecursive; } String filename = file.getName(); if (excludeInner && filename.indexOf('$') != -1) { logger.info("exclude inner class with name:" + filename); return false; } return filterClassName(filename); } }); for (File file : dirfiles) { if (file.isDirectory()) { doScanPackageClassesByFile(classes, packageName + "." + file.getName(), file.getAbsolutePath(), recursive); } else { String className = file.getName().substring(0, file.getName().length() - 6); try { classes.add(Thread.currentThread().getContextClassLoader() .loadClass(packageName + '.' + className)); } catch (ClassNotFoundException e) { logger.error("IOException error:", e); } } } } /** * 根据过滤规则判断类名 * @param className * @return */ private boolean filterClassName(String className) { if (!className.endsWith(".class")) { return false; } if (null == this.classFilters || this.classFilters.isEmpty()) { return true; } String tmpName = className.substring(0, className.length() - 6); boolean flag = false; for (String str : classFilters) { String tmpreg = "^" + str.replace("*", ".*") + "$"; Pattern p = Pattern.compile(tmpreg); if (p.matcher(tmpName).find()) { flag = true; break; } } return (checkInOrEx && flag) || (!checkInOrEx && !flag); } /** * @return the excludeInner */ public boolean isExcludeInner() { return excludeInner; } /** * @return the checkInOrEx */ public boolean isCheckInOrEx() { return checkInOrEx; } /** * @return the classFilters */ public List<String> getClassFilters() { return classFilters; } /** * @param pExcludeInner the excludeInner to set */ public void setExcludeInner(boolean pExcludeInner) { excludeInner = pExcludeInner; } /** * @param pCheckInOrEx the checkInOrEx to set */ public void setCheckInOrEx(boolean pCheckInOrEx) { checkInOrEx = pCheckInOrEx; } /** * @param pClassFilters the classFilters to set */ public void setClassFilters(List<String> pClassFilters) { classFilters = pClassFilters; } /** * @param args */ public static void main(String[] args) { // 自定义过滤规则 List<String> classFilters = new ArrayList<String>(); classFilters.add("File*"); // 创建一个扫描处理器,排除内部类 扫描符合条件的类 ClassPathScanHandler handler = new ClassPathScanHandler(true, true, classFilters); System.out .println("开始递归扫描jar文件的包:org.apache.commons.io 下符合自定义过滤规则的类..."); Set<Class<?>> calssList = handler.getPackageAllClasses( "org.apache.commons.io", true); for (Class<?> cla : calssList) { System.out.println(cla.getName()); } System.out.println("开始递归扫描file文件的包:michael.hessian 下符合自定义过滤规则的类..."); classFilters.clear(); classFilters.add("Hessian*"); calssList = handler.getPackageAllClasses("michael.hessian", true); for (Class<?> cla : calssList) { System.out.println(cla.getName()); } } } |
测试运行结果如下:
1 2 3 4 5 6 7 |
开始递归扫描jar文件的包:org.apache.commons.io 下符合自定义过滤规则的类.. org.apache.commons.io.FileCleaner org.apache.commons.io.filefilter.FileFilterUtils org.apache.commons.io.FileUtils 开始递归扫描file文件的包:michael.hessian 下符合自定义过滤规则的类... michael.hessian.client.HessianClientTest michael.hessian.client.HessianSpringClient |
原创文章,转载请注明: 转载自micmiu – 软件开发+生活点滴[ http://www.micmiu.com/ ]
😛 不错,不过getPackageAllClasses方法判断protocol的时候,没有判断vfs,因为jboss as 7 里面使用的vfs。
这个vfs还真不了解的