码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 升级包版本之后Reflections反射包在springboot jar环境下扫描不到class排查过程记录


    📢📢📢📣📣📣
    哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝
    一位上进心十足的【Java ToB端大厂领域博主】!😜😜😜
    喜欢java和python,平时比较懒,能用程序解决的坚决不手动解决😜😜😜

    ✨ 如果有对【java】感兴趣的【小可爱】,欢迎关注我

    ❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
    ————————————————

    如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。

    今天集团将大家使用的三方包的版本进行了升级,其中涉及反射的Reflection的包,Reflections工具的时候(Jar包的版本是org.reflections:reflections:0.10.2),发现在IntelliJ IDEA中运行是能正常扫描出Class对象,但是部署在测试环境或者本地以Jar报运行时,扫描不出来,所以Debug了Reflections源码。

    下面是创建Reflection对象的写法,这个在0.9.x版本的时候是没问题的,但是升级到0.10之后就有问题了,找了好半天才解决问题,这里记录一下解决问题的心得和过程,供大家参考。

     点进去最终会调用这个方法来初始化配置

    1. public static ConfigurationBuilder build(Object... params) {
    2. final ConfigurationBuilder builder = new ConfigurationBuilder();
    3. // flatten
    4. List parameters = new ArrayList<>();
    5. for (Object param : params) {
    6. if (param.getClass().isArray()) { for (Object p : (Object[]) param) parameters.add(p); }
    7. else if (param instanceof Iterable) { for (Object p : (Iterable) param) parameters.add(p); }
    8. else parameters.add(param);
    9. }
    10. ClassLoader[] loaders = Stream.of(params).filter(p -> p instanceof ClassLoader).distinct().toArray(ClassLoader[]::new);
    11. if (loaders.length != 0) { builder.addClassLoaders(loaders); }
    12. FilterBuilder inputsFilter = new FilterBuilder();
    13. builder.filterInputsBy(inputsFilter);
    14. for (Object param : parameters) {
    15. if (param instanceof String && !((String) param).isEmpty()) {
    16. builder.forPackage((String) param, loaders);
    17. inputsFilter.includePackage((String) param);
    18. } else if (param instanceof Class && !Scanner.class.isAssignableFrom((Class) param)) {
    19. builder.addUrls(ClasspathHelper.forClass((Class) param, loaders));
    20. inputsFilter.includePackage(((Class) param).getPackage().getName());
    21. } else if (param instanceof URL) {
    22. builder.addUrls((URL) param);
    23. } else if (param instanceof Scanner) {
    24. builder.addScanners((Scanner) param);
    25. } else if (param instanceof Class && Scanner.class.isAssignableFrom((Class) param)) {
    26. try { builder.addScanners(((Class) param).getDeclaredConstructor().newInstance()); }
    27. catch (Exception e) { throw new RuntimeException(e); }
    28. } else if (param instanceof Predicate) {
    29. builder.filterInputsBy((Predicate) param);
    30. } else throw new ReflectionsException("could not use param '" + param + "'");
    31. }
    32. if (builder.getUrls().isEmpty()) {
    33. // scan all classpath if no urls provided todo avoid
    34. builder.addUrls(ClasspathHelper.forClassLoader(loaders));
    35. }
    36. return builder;
    37. }
    38. 在For循环中第一个if,如果是String类型的参数,就会设置package,然后会设置filter,问题就出现在这里。这种简写方式,filter是和包名一样的。在本地IDEA中,所有文件都是在out目录下,文件的目录是正常包名开头,如下格式

      com/jay/userinterface/authority/model/dto/ProductVO.class

      但是如果是以Jar包运行的方式,因为SpringBoot 2.x版本打包时会做一些处理(加一些启动类),导致文件结构会发生变化(读者可以解压一个SpringBoot的Jar包看看实际结构)。这种情况下,获取文件的名称是如下格式

      在扫描过程中,这些文件都过不了Filter的校验。

      大致过程就是在Reflections类中scan()方法,对每个文件都会根据Filter过滤下,这个Filter就是一个正则表达式的匹配,表达式就是com/jay/userinterface/*,以Jar包方式运行的话,所有文件都会被过滤掉,扫描结果就为空。
       

      解决方案

      使用另外一种写法,自己构造Reflections的 Configuration,手动设置Filter

      1. Reflections reflections = new Reflections(new ConfigurationBuilder()
      2. .forPackages(packageName)
      3. .filterInputsBy(new FilterBuilder().includePackage("BOOT-INF.classes." + packageName))
      4. .setScanners(Scanners.MethodsAnnotated));

      我这里面是直接加了前缀,每个文件在Jar包中的实际路径,和Springboot打包后文件格式有关,Springboot 1.x版本应该是不用改的。

      也可以通过FilterBuilder的includePattern()方法来直接写正则表达式,兼容IDEA运行和Jar包运行的方式。

    39. 相关阅读:
      取消本次commit,git远程和本地同步,SourceTree分支合并
      毕设(5)—笛卡尔空间轨迹规划(直线、圆弧)
      navicat升级后,失效,重新ok,navicat彻底卸载
      功能测试进阶自动化测试?这9个必备自动化技能看看你有没有掌握...
      开发、调试环境搭建实践及把物理机做成虚拟机
      留学生朋友问我有没有学过《数值分析》
      爬虫逆向实战(34)-某视综数据(MD5、AES)
      解决github ping不通的问题(1024程序员节快乐!
      kafka的Java客户端消费者
      cmdb运维管理平台,IT资源配置管理
    40. 原文地址:https://blog.csdn.net/qq_29235677/article/details/133819317
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号