[编织消息框架][JAVA核心技术]动态代理应用9-扫描class
Posted solq321
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[编织消息框架][JAVA核心技术]动态代理应用9-扫描class相关的知识,希望对你有一定的参考价值。
之前介绍的annotationProcessor能在编译时生成自定义class,但有个缺点,只能每次添加/删除java文件才会执行,那天换了个人不清楚就坑大了
还记得之前介绍的编译时处理,懒处理,还有个预处理没介绍对吧
预处理:应用程序启动前做的处理,如setup
扫描class处理
1.从ClassLoader 和 System.getProperty("java.class.path") 读取所有classPath
2.解释每个classPath ,用正则匹配jar/class 文件
3.正则提取class文件类名,转换成class给上层处理
1 public class PackageScanner { 2 private static final Logger LOGGER = LoggerFactory.getLogger(PackageScanner.class); 3 4 /** 5 * @param packageNames 6 * 过滤的包名,如果为NULL即扫描所有类 7 */ 8 public static void scan(Consumer<Class<?>> atcion, final String... packageNames) { 9 Set<String> classPath = new HashSet<>(); 10 Set<String> filterPackage = new HashSet<>(); 11 if (packageNames == null || packageNames.length == 0) { 12 String classpathProp = System.getProperty("java.class.path"); 13 if (classpathProp != null) { 14 String[] classpathEntries = classpathProp.split(File.pathSeparator); 15 for (String cpe : classpathEntries) { 16 cpe = trimr(cpe, \'/\'); 17 classPath.add(new File(cpe).getAbsolutePath()); 18 } 19 } 20 ClassLoader cl = ClassLoader.getSystemClassLoader(); 21 URL[] urls = ((URLClassLoader) cl).getURLs(); 22 for (URL url : urls) { 23 String path = trimr(url.getPath(), \'/\'); 24 classPath.add(new File(path).getAbsolutePath()); 25 } 26 } else { 27 Collections.addAll(classPath, packageNames); 28 Collections.addAll(filterPackage, packageNames); 29 } 30 31 /*** 32 * 扫描有三种策略 33 * 1.jar文件 34 * 2.class文件 35 * 3.classPath目录 36 * */ 37 38 for (String path : classPath) { 39 try { 40 if (path.endsWith(".jar")) { 41 parseJar(path, filterPackage, atcion); 42 }else if (new File(path).isDirectory()) { 43 parseFile(path, null, filterPackage, atcion); 44 } else { 45 final String packageDirectory = path.replace(\'.\', \'/\'); 46 final Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirectory); 47 while (urls.hasMoreElements()) { 48 final URL url = urls.nextElement(); 49 if ("file".equals(url.getProtocol())) { 50 parseFile(url.getPath(), url.getPath().replace(packageDirectory, ""), filterPackage,atcion); 51 } else if ("jar".equals(url.getProtocol())) { 52 parseJar(url.getPath(),filterPackage, atcion); 53 } 54 } 55 } 56 } catch (Exception exception) { 57 throw new RuntimeException(exception); 58 } 59 } 60 } 61 }
parseJar,parseFile 比较长,感兴趣读者可查源码分析
有的JAR里的类读会出错,原因是没有依赖完整的包
测试:
1 public class TestScanClass { 2 3 @Test 4 public void testAll() { 5 PackageScanner.scan((clz) -> { 6 // System.out.println(clz); 7 }); 8 } 9 10 @Test 11 public void testFilter1() { 12 PackageScanner.scan((clz) -> { 13 System.out.println(clz); 14 } , "com.eyu.onequeue"); 15 } 16 17 @Test 18 public void testFilter() { 19 Set<Class<?>> values = new HashSet<>(); 20 PackageScanner.scan((clz) -> { 21 QModel modelAnno = ReflectUtil.getAnno(clz, QModel.class); 22 if (modelAnno == null) { 23 return; 24 } 25 values.add(clz); 26 } , "com.eyu.onequeue"); 27 for (Class<?> clz : values) { 28 if (clz.isInterface()) { 29 QRpcFactory.registerSendProxy(clz); 30 System.out.println("registerSendProxy : " + clz); 31 } else { 32 try { 33 QRpcFactory.registerReceiveProxy(clz.newInstance()); 34 System.out.println("registerReceiveProxy : " + clz); 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 } 39 } 40 } 41 }
以上是关于[编织消息框架][JAVA核心技术]动态代理应用9-扫描class的主要内容,如果未能解决你的问题,请参考以下文章
[编织消息框架][JAVA核心技术]动态代理应用7-实现设计