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

需求:
要实现指定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版本有了重大更新。跟踪源码
Reflections反射包在springboot jar环境下扫描不到class排查过程_第1张图片
重点是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;
}

Reflections反射包在springboot jar环境下扫描不到class排查过程_第2张图片
重点就是这个defaultUrlTypes。
Reflections反射包在springboot jar环境下扫描不到class排查过程_第3张图片
Reflections反射包在springboot jar环境下扫描不到class排查过程_第4张图片
主要涉及到了这个正则:
Reflections反射包在springboot jar环境下扫描不到class排查过程_第5张图片
进行了取反,即不支持springboot打包jar的方式。

再看下0.9.11版本的
Reflections反射包在springboot jar环境下扫描不到class排查过程_第6张图片
对比之下,就是没有新版取反的条件。

你可能感兴趣的:(Java基础,spring,boot,jar,java,reflections)