之前介绍的annotationProcessor能在编译时生成自定义class,但有个缺点,只能每次添加/删除java文件才会执行,那天换了个人不清楚就坑大了

还记得之前介绍的编译时处理,懒处理,还有个预处理没介绍对吧

预处理:应用程序启动前做的处理,如setup

扫描class处理

1.从ClassLoader 和 System.getProperty("java.class.path") 读取所有classPath

2.解释每个classPath ,用正则匹配jar/class 文件

3.正则提取class文件类名,转换成class给上层处理

 public class PackageScanner {
private static final Logger LOGGER = LoggerFactory.getLogger(PackageScanner.class); /**
* @param packageNames
* 过滤的包名,如果为NULL即扫描所有类
*/
public static void scan(Consumer<Class<?>> atcion, final String... packageNames) {
Set<String> classPath = new HashSet<>();
Set<String> filterPackage = new HashSet<>();
if (packageNames == null || packageNames.length == 0) {
String classpathProp = System.getProperty("java.class.path");
if (classpathProp != null) {
String[] classpathEntries = classpathProp.split(File.pathSeparator);
for (String cpe : classpathEntries) {
cpe = trimr(cpe, '/');
classPath.add(new File(cpe).getAbsolutePath());
}
}
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
String path = trimr(url.getPath(), '/');
classPath.add(new File(path).getAbsolutePath());
}
} else {
Collections.addAll(classPath, packageNames);
Collections.addAll(filterPackage, packageNames);
} /***
* 扫描有三种策略
* 1.jar文件
* 2.class文件
* 3.classPath目录
* */ for (String path : classPath) {
try {
if (path.endsWith(".jar")) {
parseJar(path, filterPackage, atcion);
}else if (new File(path).isDirectory()) {
parseFile(path, null, filterPackage, atcion);
} else {
final String packageDirectory = path.replace('.', '/');
final Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirectory);
while (urls.hasMoreElements()) {
final URL url = urls.nextElement();
if ("file".equals(url.getProtocol())) {
parseFile(url.getPath(), url.getPath().replace(packageDirectory, ""), filterPackage,atcion);
} else if ("jar".equals(url.getProtocol())) {
parseJar(url.getPath(),filterPackage, atcion);
}
}
}
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
}

parseJar,parseFile 比较长,感兴趣读者可查源码分析

有的JAR里的类读会出错,原因是没有依赖完整的包

测试:

 public class TestScanClass {

     @Test
public void testAll() {
PackageScanner.scan((clz) -> {
// System.out.println(clz);
});
} @Test
public void testFilter1() {
PackageScanner.scan((clz) -> {
System.out.println(clz);
} , "com.eyu.onequeue");
} @Test
public void testFilter() {
Set<Class<?>> values = new HashSet<>();
PackageScanner.scan((clz) -> {
QModel modelAnno = ReflectUtil.getAnno(clz, QModel.class);
if (modelAnno == null) {
return;
}
values.add(clz);
} , "com.eyu.onequeue");
for (Class<?> clz : values) {
if (clz.isInterface()) {
QRpcFactory.registerSendProxy(clz);
System.out.println("registerSendProxy : " + clz);
} else {
try {
QRpcFactory.registerReceiveProxy(clz.newInstance());
System.out.println("registerReceiveProxy : " + clz);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

[编织消息框架][JAVA核心技术]动态代理应用9-扫描class的更多相关文章

  1. [编织消息框架][JAVA核心技术]动态代理介绍

    由于java是种强类型静态语言,在执行时无法动态生成代码,静态语言基本都有这特性 动态生成代码有几种好处,也是弱类型语言的优点 1.部份逻辑可以实现热更新 2.远程调用实现非常适合 3.能动态生成扩展 ...

  2. [编织消息框架][JAVA核心技术]动态代理应用12-总结

    动态代理这篇比较长,是框架组成的重要基础 回顾下学到的应用技术 1.异常应用 2.annotation技术 3.数值与逻辑分享 4.jdk.cglib.javassist等动态代理技术 5.懒处理.预 ...

  3. [编织消息框架][JAVA核心技术]动态代理应用4

    基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...

  4. [编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现

    private static Map<Short, Map<Byte, Method>> RECEIVE_METHOD_INFO = new HashMap<>() ...

  5. [编织消息框架][JAVA核心技术]动态代理应用7-IRpcSend实现

    根据设计生成两个接口,IRpcSend send方法返回数据要求包装成QResult对象 public interface IRpcSend { public <T> QResult< ...

  6. [编织消息框架][JAVA核心技术]动态代理应用4-annotationProcessor

    基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...

  7. [编织消息框架][JAVA核心技术]动态代理应用2

    接下来如何实现 第一步:先把服务类,调用方法转换成数字,方便传输 第二步:提取元信息,提取又有三种方式,三种各有优点,最优方式是第一种 1.编译java时处理 2.程序启动时处理,预处理 3.调用时处 ...

  8. [编织消息框架][JAVA核心技术]动态代理应用5-javassist

    基础部份: 修改class我们用到javassist,在pom.xml添加 <properties> <javassist.version>3.18.2-GA</java ...

  9. [编织消息框架][JAVA核心技术]动态代理应用10-水平扩展方案

    服务分为系统服务同用户服务两种 水平扩展是基于系统服务,而拆分方式又有几种方案,按数据跟业务情况来做决策 1.每个服务独立存储(图1):每个服务只负责一个或多个领域实体存储,A服务不能直接修改B服务的 ...

随机推荐

  1. 读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用

    一个关于赋值的有趣的事情是你可以将它们链在一起: int x, y, z; x = y = z = ; // chain of assignments 同样有趣的是赋值采用右结合律,所以上面的赋值链被 ...

  2. 【Java基础】HashMap工作原理

    HashMap Hash table based implementation of the Map interface. This implementation provides all of th ...

  3. 翻译:如何使用CSS实现多行文本的省略号显示

    本文翻译自CSS Ellipsis: How to Manage Multi-Line Ellipsis in Pure CSS,文中某些部分有些许改动,并添加译者的一些感想,请各位读者谅解. 合理的 ...

  4. 9 个用于移动APP开发的顶级 JavaScript 框架

    顶级 Java 框架 对于Web开发而言,Java是一个有前途的编程语言,并且在不久的将来它将依然在这个领域大放光彩.Java在移动app开发上也有同样的影响吗?让我们一起来看看ValueCoders ...

  5. sqlserver的一些小知识点

    1.高效分页sql和储存过程 select top 每页条数 * from ( select ROW_NUMBER() over (order by id)as nid ,* from table01 ...

  6. 使用Spring构建RMI服务器和客户端

    上一篇文章我们实用JDK原生API构造了简单RMI应用,本篇将实用Spring框架来构造RMI的应用,实用Spring你会体验到简单,不需要那么多的条条框框,因为Spring给你做了很多封装. 项目构 ...

  7. java基础:数组的复制

  8. C#:查询某年(1900-2100)某月的日历

    using System;using System.Collections.Generic;public class Program    {     /********************主函数 ...

  9. 1682: [Usaco2005 Mar]Out of Hay 干草危机

    1682: [Usaco2005 Mar]Out of Hay 干草危机 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 391  Solved: 258[ ...

  10. 用虚拟机安装Linux系统的过程

    1.打开VMware->点击File->点击New Virtual Machine.. 2.我们选择Custom并点击Next 3.保持默认然后点next 4.选择图中所示内容,点Next ...