Ser*_*gio 7 java eclipse classloader maven-3 reflections
我正在使用Google Reflections库来查询类路径中的某些资源.这些资源与我项目中的类位于同一位置.
我写了一些单元测试,这些测试在Eclipse中作为单元测试执行时成功,但是当我尝试用Maven执行它们时(maven install例如),它们没有按预期工作.经过一些调试,显然问题是当使用Maven执行时,Reflections库找不到资源所在的类路径url.
我得出结论,研究Reflection如何确定应检查的类路径URL.作为一个例子,下面的方法显示了Reflection如何在给定类加载器的情况下找到可用的类路径URL(原始的Reflection方法已经简化了一点):
public static Set<URL> forClassLoader(ClassLoader... classLoaders) {
final Set<URL> result = Sets.newHashSet();
for (ClassLoader classLoader : classLoaders) {
while (classLoader != null) {
if (classLoader instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) classLoader).getURLs();
if (urls != null) {
result.addAll(Sets.<URL>newHashSet(urls));
}
}
classLoader = classLoader.getParent();
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
简而言之,它遍历类加载器层次结构,询问每个单独的类加载器的URL.
在Eclipse中,我使用类似这样的单元测试调用前一个方法:
ClassLoader myClassClassLoader = <MyClass>.class.getClassLoader(); //<MyClass> is in the same classpath url than the resources I need to find
Set<URL> urls = forClassLoader(myClassClassLoader);
for(URL url : urls) {
System.out.println("a url: " + url);
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,我可以看到(在许多其他URL中)作为项目的一部分配置的类路径URL:
file:<MY_PROJECT_PATH>/target/classes/
file:<MY_PROJECT_PATH>/target/test-classes/
Run Code Online (Sandbox Code Playgroud)
和思考作为一种魅力(思考应找到的资源位于其中file:<MY_PROJECT_PATH>/target/classes/).
但是,当测试由Maven执行时,我意识到forClassLoader方法返回的集合中缺少这些URL条目,并且其余的Reflections方法对此问题没有按预期工作.
"令人惊讶"的是,如果我在maven执行单元测试时写这个:
ClassLoader myClassClassLoader = <MyClass>.class.getClassLoader();
url = myClassClassLoader.getResource("anExistingResource");
System.out.println("URL: "+url); //a valid URL
Run Code Online (Sandbox Code Playgroud)
我可以看到类加载器仍然可以解析我想要找到的资源.我很困惑为什么当使用Maven执行时,forClassLoader方法不会在返回的集合中包含我的项目的类路径URL,尽管它同时能够解析位于这些URL中的资源(!).
这种行为的原因是什么?是否有任何解决方法我可以尝试使作为由Maven运行的单元测试的一部分调用的Reflections库工作?
解决了它.发布解决方案,以防将来有人发现同样的问题.
在执行项目的单元测试时,Maven不会(明确地)在类路径中包含其所有依赖项.相反,它声明了对位于"target/surefire/surefirebooter_NUMBER_THAT_LOOKS_LIKE_TIME_STAMP.jar"中的tmp jar的依赖.此jar只包含一个声明项目类路径的清单文件.
forClassLoaderReflections库中的方法不会返回一组具有有效类路径的URL (即,清除清单文件中的类路径条目).为了解决这个问题,我刚刚实现了这个简单的方法
public static Set<URL> effectiveClassPathUrls(ClassLoader... classLoaders) {
return ClasspathHelper.forManifest(ClasspathHelper.forClassLoader(classLoaders));
}
Run Code Online (Sandbox Code Playgroud)
该方法forManifest(也反思库的一部分),增加了一组被作为参数,在包含在集合中的任何jar文件清单文件中声明丢失的类路径条目的类路径的URL.通过这种方式,该方法返回一组带有项目有效类路径的URL.
| 归档时间: |
|
| 查看次数: |
2118 次 |
| 最近记录: |