zoukankan      html  css  js  c++  java
  • [编织消息框架][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 }
  • 相关阅读:
    P20 HTTP 方法的安全性与幂等性
    P19 查询参数
    P18 写代码:过滤和搜索
    P17 过滤和搜索
    P16 HTTP HEAD
    golang的json操作[转]
    Android中的Service 与 Thread 的区别[转]
    iOS的block内存管理
    Go并发编程基础(译)
    golang闭包里的坑
  • 原文地址:https://www.cnblogs.com/solq111/p/6703445.html
Copyright © 2011-2022 走看看