首页 > 代码库 > [编织消息框架][JAVA核心技术]动态代理应用9-扫描class

[编织消息框架][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     @Test11     public void testFilter1() {12         PackageScanner.scan((clz) -> {13             System.out.println(clz);14         } , "com.eyu.onequeue");15     }16 17     @Test18     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