Reflections反射包在springboot jar环境下扫描不到class排查过程

news2024/11/25 13:46:23

需求:
要实现指定pkg(如com.qiqitrue.test.pojo)扫描包下所有class类信息:使用代码如下
pkg扫描包:如com.qiqitrue.test.pojo
使用的版本:0.10.2(截至目前是最新版)发现只能在idea编译期间可以获取得到(也就是在开发阶段)。当打成了jar包之后,获取不到。
先找到了
https://github.com/CESNET/perun/pull/3836
https://github.com/ronmamo/reflections
这个。改成了如下:

Reflections reflections = new Reflections(
  new ConfigurationBuilder()
    .forPackage("com.my.project")
    // 先注释这个,一会说原因
    //.filterInputsBy(new FilterBuilder().includePackage("com.my.project")));

改了这个之后虽然能获取到。但实际上,所谓定义package,只是为classloader找路径而已。并没有指定传得包,也就是说,虽然我指定了package,但是,实际扫描得路径是target\classs(那范围可大了)。打成jar包之后获取,也是可以。貌似解决了。但如果我程序中有多次扫描不同的包下类上标注相同注解的类,那将会出现重叠的情况。
比如这样:

String pkg = "com.qiqitrue.pojo.a";//@1
Reflections reflections = new Reflections(pkg);
Set<Class<?>> resourceTypeClasses = reflections.getTypesAnnotatedWith(MyAnno.class);
log.info("扫描出类型{}资源类实体数:{}", subPathPackage, resourceTypeClasses.size());

String pkg = "com.qiqitrue.pojo.b";//@2

package com.qiqitrue.pojo.a;
@MyAnno
class A {
}

package com.qiqitrue.pojo.b;
@MyAnno
class B {
}

a和b包都有标注相同的注解情况下,那将产生重复。虽然能通过包名进行过滤,但是且不够优雅。

为了需要,就需要把filterInputsBy(new FilterBuilder().includePackage(“com.my.project”))这个也加上,发现就可以解决上面说的问题。

但是…打包jar之后运行,获取不到。最终解决是回退到版本:0.9.11
https://github.com/ronmamo/reflections/issues/373

虽然切换个版本就能解决,但是不知道为何解决了,继续刨根问底看一下,
对比两个版本的代码实现,发现0.10.X版本有了重大更新。跟踪源码
在这里插入图片描述
重点是scan()方法

protected Map<String, Map<String, Set<String>>> scan() {
   long start = System.currentTimeMillis();
   Map<String, Set<Map.Entry<String, String>>> collect = configuration.getScanners().stream().map(Scanner::index).distinct()
       .collect(Collectors.toMap(s -> s, s -> Collections.synchronizedSet(new HashSet<>())));
   Set<URL> urls = configuration.getUrls();

   (configuration.isParallel() ? urls.stream().parallel() : urls.stream()).forEach(url -> {
       Vfs.Dir dir = null;
       try {
           dir = Vfs.fromURL(url);//@1 这是重点,进入这个方法看一下
           for (Vfs.File file : dir.getFiles()) {
               if (doFilter(file, configuration.getInputsFilter())) {
                   ClassFile classFile = null;
                   for (Scanner scanner : configuration.getScanners()) {
                       try {
                           if (doFilter(file, scanner::acceptsInput)) {
                               List<Map.Entry<String, String>> entries = scanner.scan(file);
                               if (entries == null) {
                                   if (classFile == null) classFile = getClassFile(file);
                                   entries = scanner.scan(classFile);
                               }
                               if (entries != null) collect.get(scanner.index()).addAll(entries);
                           }
                       } catch (Exception e) {
                           if (log != null) log.trace("could not scan file {} with scanner {}", file.getRelativePath(), scanner.getClass().getSimpleName(), e);
                       }
                   }
               }
           }
       } catch (Exception e) {
           if (log != null) log.warn("could not create Vfs.Dir from url. ignoring the exception and continuing", e);
       } finally {
           if (dir != null) dir.close();
       }
   });

   // merge
   Map<String, Map<String, Set<String>>> storeMap =
       collect.entrySet().stream()
           .collect(Collectors.toMap(
               Map.Entry::getKey,
               entry -> entry.getValue().stream().filter(e -> e.getKey() != null)
                   .collect(Collectors.groupingBy(
                       Map.Entry::getKey,
                       HashMap::new,
                       Collectors.mapping(Map.Entry::getValue, Collectors.toSet())))));
   if (log != null) {
       int keys = 0, values = 0;
       for (Map<String, Set<String>> map : storeMap.values()) {
           keys += map.size();
           values += map.values().stream().mapToLong(Set::size).sum();
       }
       log.info(format("Reflections took %d ms to scan %d urls, producing %d keys and %d values", System.currentTimeMillis() - start, urls.size(), keys, values));
   }
   return storeMap;
}

在这里插入图片描述
重点就是这个defaultUrlTypes。
在这里插入图片描述
在这里插入图片描述
主要涉及到了这个正则:
在这里插入图片描述
进行了取反,即不支持springboot打包jar的方式。

再看下0.9.11版本的
在这里插入图片描述
对比之下,就是没有新版取反的条件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333411.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目管理的十条成功经验(建议收藏)

项目管理的十条成功经验 1、定义项目成功的标准 在项目的开始&#xff0c;要保证各方对于判断项目是否成功有统一的标准。 2、把握各种要求之间的平衡 每个项目都需要平衡它的功能、人员、预算、进度和质量目标。 3、部门客户间的沟通 坦诚地与客户、管理人员沟通那些实…

无需注册即可免费使用ChatGPT

无需注册即可免费使用ChatGPT 最近OpenAI的ChatGPT异常火爆&#xff0c;有很多人都想尝试尝试&#xff0c;但是因为一些原因折戟&#xff0c;这里提供一个免注册的体验方法&#xff0c;仅供学习交流。 一&#xff0c;首先下载vscode 官网下载地址 Visual Studio Code - Code…

文本匹配SimCSE模型代码详解以及训练自己的中文数据集

前言 在上一篇博客文本匹配中的示例代码中使用到了一个SimCSE模型&#xff0c;用来提取短文本的特征&#xff0c;然后计算特征相似度&#xff0c;最终达到文本匹配的目的。但是该示例代码中的短文本是用的英文短句&#xff0c;其实SimCSE模型也可以用于中文短文本的特征提取&a…

使用STM32 CUBE IDE配置STM32F7 用DMA传输多通道ADC数据

我的使用环境&#xff1a; 硬件&#xff1a;STM32F767ZGT6、串口1、ADC1、16MHz晶振、216MHz主频 软件&#xff1a;STM32 CUBE IDE 优点&#xff1a;不用定时触发采样&#xff0c;ADC数据是不停的实时更新&#xff0c;ADC数据的更新频率根据采样时钟和采样周期决定&#xff0c;…

负载均衡反向代理下的webshell上传+apache漏洞

目录一、负载均衡反向代理下的webshell上传1、nginx 负载均衡2、搭建环境3、负载均衡下的 WebShell连接的难点总结难点一、需要在每一台节点的相同位置都上传相同内容的 WebShell难点二、无法预测下次的请求交给哪台机器去执行。难点三、下载文件时&#xff0c;可能会出现飘逸&…

面试题:Redis的内存策略

1 Redis内存回收Redis之所以性能强&#xff0c;主要原因是基于内存存储&#xff0c;然而单节点的Redis内存不易过大&#xff0c;会影响主从同步和持久化性能我们可以通过修改配置文件设置Redis的最大内存&#xff1a;当内存存储到上限时&#xff0c;就无法存储更多的数据了。1.…

html控件Aspose.Html for .NET 授权须知

Aspose.Html for .NET是一种高级的HTML操作API&#xff0c;可让您直接在.NET应用程序中执行广泛的HTML操作任务&#xff0c;Aspose.Html for .NET允许创建&#xff0c;加载&#xff0c;编辑或转换&#xff08;X&#xff09;HTML文档&#xff0c;而无需额外的软件或工具。API还为…

Java开发学习(四十六)----MyBatisPlus新增语句之id生成策略控制及其简化配置

在前面有一篇博客&#xff1a;Java开发学习(四十一)----MyBatisPlus标准数据层&#xff08;增删查改分页&#xff09;开发&#xff0c;我们在新增的时候留了一个问题&#xff0c;就是新增成功后&#xff0c;主键ID是一个很长串的内容。 我们更想要的是按照数据库表字段进行自增…

CleanMyMac X4.12新版本下载及功能介绍

CleanMyMac X2023最新版终于迎来了又4.12&#xff0c;重新设计了 UI 元素&#xff0c;华丽的现代化风格显露无余。如今的CleanMyMac&#xff0c;早已不是单纯的系统清理工具。在逐渐融入系统优化、软件管理、文件管理等功能后&#xff0c;逐渐趋近于macOS的系统管家&#xff0c…

Python数据可视化(三)(pyecharts)

分享一些python-pyecharts作图小技巧&#xff0c;用于展示汇报。 一、特点 任何元素皆可配置pyecharts只支持python原生的数据类型&#xff0c;包括int,float,str,bool,dict,list动态展示&#xff0c;炫酷的效果&#xff0c;给人视觉冲击力 # 安装 pip install pyecharts fr…

算法训练营DAY51|300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

本期是求子序列的新的一期&#xff0c;题目前两道有一些相似之处&#xff0c;思路差不多&#xff0c;第三道有一点难度&#xff0c;但并不意味着第一道没有难度&#xff0c;没有做过该类型题的选手&#xff0c;并不容易解出题解。 300. 最长递增子序列 - 力扣&#xff08;Leet…

22级浙江大学MBA笔试备考的若干经验分享

我是浙江大学2022级的一名新生&#xff0c;虽然没有参加提前批面试&#xff0c;但是通过笔试的有序备考最终也有幸上岸浙大&#xff0c;对于部分提前批面试没拿到优秀资格的考友&#xff0c;今天我想把自己的笔试上岸经验做个总结&#xff0c;给大家提供一个参考模版。 先…

TC358774XBG/TC358775XBG替代方案|CS5518替代TC358774XBG/TC358775XBG设计DSI转LVSD设计资料

TC358774XBG/TC358775XBG替代方案|CS5518替代TC358774XBG/TC358775XBG设计DSI转LVSD设计资料 TC358774XBG/TC358775XBG 芯片的主要功能是作为 DSI - LVDS 通信协议桥接&#xff0c;主芯片的视频数据可通过 DSI 链路流 出&#xff0c;以驱动兼容 LVDS 的显示板。换句话说&#x…

百度官宣在前,阿里、京东在后,互联网大厂向ChatGPT而生?

ChatGPT蹿红后&#xff0c;互联网科技公司都坐不住了。 最早&#xff0c;百度正式对外官宣类ChatGPT项目“文心一言”&#xff08;ERNIE Bot&#xff09;。据笔者了解&#xff0c;该产品将于三月份完成内测&#xff0c;面向公众开放。 紧随其后&#xff0c;阿里巴巴公布阿里版…

流浪地球 | 建筑人是如何看待小破球里的黑科技的?

大家好&#xff0c;这里是建模助手。 想问问大家今年贺岁档&#xff0c;都跟上没有&#xff0c;今天请允许我蹭一下热点表达一下作为一个科幻迷的爱国之情。 抛开大刘的想象力、各种硬核科技&以及大国情怀不提&#xff0c;破球2中的传承还是让小编很受感动&#xff0c;无…

【2023】Prometheus-Prometheus与Alertmanager配置详解

记录一下Prometheus与Alertmanager的配置参数等内容 目录1.Prometheus1.1.prometheus.yml1.2.告警规则定义2.alertmanager2.1.alertmanager.yml2.1.1.global&#xff1a;全局配置2.1.1.1.以email方式作为告警发送方2.1.1.2.以wechat方式作为告警发送方2.1.1.3.以webhook方式作为…

c++基础入门二

一、数组的引用int main() {int a 10, b 20;int ar[10] { 1,2,3,4,6,7 };int& x ar[0];int& p[5] ar;//errorint(&p)[10] ar;//引用整个数组的大小sizeof(ar)int(*p)[10] &ar;//typesize表示整个数组//只有在这三种情况下代表整个数组&#xff0c;其他情…

C++ 浅谈之 STL Vector

C 浅谈之 STL Vector HELLO&#xff0c;各位博友好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 这里是 C 浅谈系列&#xff0c;收录在专栏 C 语言中 &#x1f61c;&#x1f61c;&#x1f61c; 本系列阿呆将记录一些 C 语言重要的语法特性 &#x1f3c3;&…

18-考虑柔性负荷的综合能源系统低碳经济优化调度MATLAB程序

参考文献&#xff1a;考虑柔性负荷的综合能源系统低碳经济优化调度_薛开阳考虑用户侧柔性负荷的社区综合能源系统日前优化调度_刘蓉晖主要内容&#xff1a;基础模型参考刘蓉晖的论文&#xff0c;主要做了场景1、2、3&#xff1b;碳交易模型采用薛开阳论文中的。采用CPIEX求解某…

ArcGIS API for JavaScript 4.15系列(2)——Dojo中的dom操作

1、前言 ArcGIS API for JavaScript是基于Dojo框架编写的开发包&#xff0c;因此了解并掌握Dojo的相关基础知识是极为必要的。很多开发者都反馈过一个问题&#xff0c;那就是一看见ArcGIS API for JavaScript里那些奇形怪状的代码就觉得无从下手。有一点必须得承认&#xff1a…