org.reflections包下ClasspathHelper.forPackage方法的使用误区
来源:互联网 发布:淘宝网农村怎么加盟 编辑:程序博客网 时间:2024/06/11 10:43
今天在项目需求中遇到要扫描某一特定路径下class的问题,在代码看到如下使用:
private void scanAnnotations() { Reflections packageReflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(pkg)) .setScanners(new FieldAnnotationsScanner())); //1.对静态字段的注解初始化 scanStaticStringAnnotation(packageReflections); //2.对枚举类型字段的注解初始化 scanEnumAnnotation(packageReflections); }
其中ClasspathHelper.forPackage方法的源码如下: /** * Returns a distinct collection of URLs based on a package name. * <p> * This searches for the package name as a resource, using {@link ClassLoader#getResources(String)}. * For example, {@code forPackage(org.reflections)} effectively returns URLs from the * classpath containing packages starting with {@code org.reflections}. * <p> * If the optional {@link ClassLoader}s are not specified, then both {@link #contextClassLoader()} * and {@link #staticClassLoader()} are used for {@link ClassLoader#getResources(String)}. * <p> * The returned URLs retainsthe order of the given {@code classLoaders}. * * @return the collection of URLs, not null */ public static Collection<URL> forPackage(String name, ClassLoader... classLoaders) { return forResource(resourceName(name), classLoaders); }
注意标红的句子,是不是很容易让人理解成返回的结果就是你要传入的路径?其实它的返回结果是你所传入路径的上一级路径,也就是包含你所传入路径的那个路径。继续点进去可以看到:public static Collection<URL> forResource(String resourceName, ClassLoader... classLoaders) { final List<URL> result = new ArrayList<URL>(); final ClassLoader[] loaders = classLoaders(classLoaders); for (ClassLoader classLoader : loaders) { try { final Enumeration<URL> urls = classLoader.getResources(resourceName); while (urls.hasMoreElements()) { final URL url = urls.nextElement(); int index = url.toExternalForm().lastIndexOf(resourceName); if (index != -1) { result.add(new URL(url.toExternalForm().substring(0, index))); } else { result.add(url); //whatever } } } catch (IOException e) { if (Reflections.log != null) { Reflections.log.error("error getting resources for " + resourceName, e); } } } return distinctUrls(result); }
这里就是真正处理并得到路径的地方,关键就在于这个substring的用处,是不是很坑..这是Github上有人遇到的同样问题:
Collection<URL> urls = ClasspathHelper.forPackage("foo.reflections.v1"); System.out.println("URLS="+urls); config.addUrls(urls);Output is:URLS=[file:/tmp/Code/sandbox/build/classes/main/]which is the root directory and when scan by Reflections is done, everything is scanned from root.The issue seems to be with ClasspatHelper:107result.add(new URL(url, url.toExternalForm().substring(0, index)));The workaround is to do:Reflections reflections = new Reflections("foo.reflections.v1")and bypass ClasspathHelper.forPackage call, which the documentation states as the correct way to do it.This also affects using ConfigurationBuilder.forPackages, as any valid package name is ignored and scanning starts at root.At least one other 3rd party library is affected by this, Swagger which winds up scanning everything on startup and significantly
impacts the startup time of api servers that use it. At the moment I have not found a way to force Swagger to use the other
Reflections constructor nor to access the internal ConfigurationBuilder.The ultimate issue is that ClasspathHelper.forPackage should be returning the URL for that package and not root.
阅读全文
0 0
- org.reflections包下ClasspathHelper.forPackage方法的使用误区
- Linux下使用date的误区
- Directory.GetFiles 方法 中使用的误区
- Reflections
- Reflections
- 使用org.apache.commons.lang.StringUtils方法containsAny误区 看看你们遇到过没有
- org.json的包的使用
- Java创建和解析Json数据方法(二)——org.json包的使用
- Java创建和解析Json数据方法(二)——org.json包的使用
- Java创建和解析Json数据方法(二)——org.json包的使用
- 倒影(reflections)效果的实现
- 倒影(reflections)效果的实现
- chrome下使用的let,const变量的误区
- 使用缓存的9大误区(下)
- 使用缓存的9大误区(下)
- 使用缓存的9大误区(下)
- 使用缓存的9大误区(下)
- 使用缓存的9大误区 【下】
- c语言面试题大汇总
- 算术运算
- HDU2003
- win10使用tensorboard遇到无法显示问题
- css复习
- org.reflections包下ClasspathHelper.forPackage方法的使用误区
- hadoop HDFS常用文件操作命令
- 并发编程基础
- YUV4:2:0格式的帧信息
- jsp页面查询附件并下载
- C语言创建单向链表之逆向建链
- bzoj 2730
- 顺序表、链表封装结构
- C++ STL-Vector基本原理