[编织消息框架][JAVA核心技术]动态代理应用9-扫描class
之前介绍的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的更多相关文章
- [编织消息框架][JAVA核心技术]动态代理介绍
由于java是种强类型静态语言,在执行时无法动态生成代码,静态语言基本都有这特性 动态生成代码有几种好处,也是弱类型语言的优点 1.部份逻辑可以实现热更新 2.远程调用实现非常适合 3.能动态生成扩展 ...
- [编织消息框架][JAVA核心技术]动态代理应用12-总结
动态代理这篇比较长,是框架组成的重要基础 回顾下学到的应用技术 1.异常应用 2.annotation技术 3.数值与逻辑分享 4.jdk.cglib.javassist等动态代理技术 5.懒处理.预 ...
- [编织消息框架][JAVA核心技术]动态代理应用4
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
- [编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现
private static Map<Short, Map<Byte, Method>> RECEIVE_METHOD_INFO = new HashMap<>() ...
- [编织消息框架][JAVA核心技术]动态代理应用7-IRpcSend实现
根据设计生成两个接口,IRpcSend send方法返回数据要求包装成QResult对象 public interface IRpcSend { public <T> QResult< ...
- [编织消息框架][JAVA核心技术]动态代理应用4-annotationProcessor
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
- [编织消息框架][JAVA核心技术]动态代理应用2
接下来如何实现 第一步:先把服务类,调用方法转换成数字,方便传输 第二步:提取元信息,提取又有三种方式,三种各有优点,最优方式是第一种 1.编译java时处理 2.程序启动时处理,预处理 3.调用时处 ...
- [编织消息框架][JAVA核心技术]动态代理应用5-javassist
基础部份: 修改class我们用到javassist,在pom.xml添加 <properties> <javassist.version>3.18.2-GA</java ...
- [编织消息框架][JAVA核心技术]动态代理应用10-水平扩展方案
服务分为系统服务同用户服务两种 水平扩展是基于系统服务,而拆分方式又有几种方案,按数据跟业务情况来做决策 1.每个服务独立存储(图1):每个服务只负责一个或多个领域实体存储,A服务不能直接修改B服务的 ...
随机推荐
- 快速排序OC、Swift版源码
前言: 你要问我学学算法在工作当中有什么用,说实话,当达不到那个地步的时候,可能我们不能直接的感觉到它的用处!你就抱着这样一个心态,当一些APP中涉及到算法的时候我不想给其他人画界面!公司的项目也是暂 ...
- 云服务器spark集群搭建
---恢复内容开始--- 1:去官网下载spark http://spark.apache.org 2:解压,然后在自己的机器上编译conf中的两个文件 mv slaves.template slav ...
- 令人眼前一亮的下拉式终端 Tilda & Guake
前言 老夫是 Linux 的老用户. 大一的时候某不方便透露姓名的校内组织给了一个 Fedora 13 的安装光盘,然后老夫学会了重装 Windows. 大二的时候知道了 Ubuntu ,开始在虚拟机 ...
- Selenium 显示等待和隐式等待
1. 设置显示等待 Java代码: 1 2 3 4 5 public static WebElement WaitForElement(WebDriver driver, String locator ...
- 转:关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
1. JSON.parse(jsonString): 在一个字符串中解析出JSON对象 ? 1 2 3 var str = '[{"href":"baidu.com&qu ...
- 弹出层js要这样加才不会失效
$('body').on('click','.check_eln',function(){ $('#eln_show').toggleClass('hidden'); });
- 一个可以将 json 字符串 直接绑定到 view 上的Android库
android-data-binding 这是一个可以将 json 字符串 直接绑定到 view 上的库, 不用先将 json 转换为 model 类. 传送门(https://github.com/ ...
- 4052: [Cerc2013]Magical GCD
4052: [Cerc2013]Magical GCD Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 148 Solved: 70[Submit][ ...
- C++primer拾遗(第二章:变量和基本类型)
这是我对c++primer第二章的一个整理总结,算是比较适用于我自己吧,一小部分感觉不用提及的就省略了,只提了一下平时不注意,或者不好记住的内容. 排版太费劲了,直接放了图片格式.从自己的oneNot ...
- SQL基本用法-行转列
/* SELECT <非透视的列>, [第一个透视的列] AS <列名称>, [第二个透视的列] AS <列名称>, ... [最后一个透视的列] AS <列 ...