[编织消息框架][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服务的 ...
随机推荐
- Laravel使用Seeder自动填充数据
要查看代码,可以点击 或者转到链接:https://github.com/laravel/framework Laravel自动填充数据使用的是Seeder类 <?php use Illumin ...
- querySelectorAll与getElementsBy对比有什么不同
querySelectorAll与getElementsBy对比有什么不同javascript中的querySelectorAll与getElementsBy都可以获取dom元素对象,但是他们又有什么 ...
- Visual Studio 2017正式版发布全纪录
又是一年发布季,微软借着Visual Studio品牌20周年之际,于美国太平洋时间2017年3月7日9点召开发布会议,宣布正式发布新一代开发利器Visual Studio 2017.同时发布的还有 ...
- Eclipse标准版安装J2EE插件
WTP 使用Eclipse IDE for Java EE Developers是非常方便,但是太大,我喜欢按需配置.首先我们来了解什么是WTP. WTP(Web Tools Platform )项目 ...
- 《Shell脚本学习指南》学习笔记之变量、判断和流程控制
变量 定义变量 可以使用export和readonly来设置变量,export用于修改或打印环境变量,readonly则使得变量不得修改.语法: export name[=word] ... read ...
- .NET 知识整理笔记
本文纯属自己理解着写的,如果有什么错误或者不全面希望读者能够加以补充!~ 1.Web.Config配置文件的节点操作. 在Web.Config中写入. <configuration> &l ...
- background-image 与 img 动画性能对比
开发H5常常会用到滑屏,目前大部分滑屏插件都是通过控制页面的transform属性来实现.尽管如此,我总是发现自己的H5滑动起来就是不如网上一些优秀案例流畅,表现为滑动动画会出现卡顿.跳帧. 后来我发 ...
- Node.js + React + MongoDB 实现 TodoList 单页应用
之前用 Ant Design 开发了一个项目,因此对 React 的特性有了一定的了解,React 使用封装组件的思想,组件各自维护自己的状态和 UI, 组件之间通过 props 传递数据和方法.当状 ...
- ST HW2 fault & error & failure
Software Testing 3014218128 牛菲菲 Below are two faulty programs. Each includes a test case that result ...
- .Net程序员学用Oracle系列(22):分析函数(OVER)
1.函数语法 1.1.语法概述 1.2.窗口详解 1.2.1.ROWS 窗口 1.2.2.RANGE 窗口 2.函数用法 2.1.普通统计类函数 2.2.数据排序类函数 2.3.数据分布类函数 2.4 ...