我使用Reflections来查找具有特定注释的类。我的项目结构如下
WAR包:web - inf/classes/包……/ClassAnnoted1.class
war包含的一个JAR包,其中包含一个执行此代码的类:
Reflections reflections= new Reflections(ClasspathHelper.forWebInfClasses(servletContext))
Set set= reflections.getTypesAnnotatedWith(CustomAnnotation.class)
CustomAnnotation也存在于JAR包中。
设置大小是正确的(即如果我有3个类的注释在我的WAR jar,设置大小返回为3),但它里面的所有元素都是空的,而不是类。我需要获取类并检查JAR的类中的注释参数。
有人知道为什么会发生这种情况吗?
编辑:Reflections reflections= new Reflections("com.my.customAnnotededClasses"); //package that my annoted class is in
Set set= reflections.getTypesAnnotatedWith(CustomAnnotation.class);
也不起作用,在这种情况下,设置的长度是零,而不是带有注释的类的数量。
编辑2:好的,真正的问题是我将整个应用程序打包为EAR,所以我有以下内容:
EAR
----> WAR
----> JAR
jar包含在EAR lib文件夹中,而不是WAR lib文件夹中。所以jar类不能看到war类,一旦我让war直接依赖jar,像这样:
EAR
----> WAR
---------> JAR
它开始工作了。但是最初的问题仍然存在,可能在某些情况下,我希望Jar类包含在EAR中而不是WAR中(例如,如果我有多个需要使用我的Jar的战争)。
我想我不能使用反射库。所以我手工完成了:
public static List<Class<?>> getClassesAnnotatedWith(Class annotation, ServletContext servletContext) {
List<Class<?>> webClasses, jarClasses;
webClasses= getClassesAnnotedWithFromClassLoader(annotation, servletContext.getClassLoader());
jarClasses= getClassesAnnotedWithFromClassLoader(annotation, Thread.currentThread().getContextClassLoader());
for (Class<?> jarClass : jarClasses) {
Class<?> elementToAdd= null;
for (Class<?> webClass : webClasses) {
if ( ! jarClass.getName().equals(webClass.getName())) {
elementToAdd= jarClass;
}
}
if(elementToAdd != null) {
webClasses.add(elementToAdd);
}
}
return webClasses;
}
private static List<Class<?>> getClassesAnnotedWithFromClassLoader(Class annotation, ClassLoader classLoader) {
List<Class<?>> classes= new ArrayList<Class<?>>();
Class<?> classLoaderClass= classLoader.getClass();
while (! classLoaderClass.getName().equals("java.lang.ClassLoader")) {
classLoaderClass= classLoaderClass.getSuperclass();
}
try {
Field fldClasses= classLoaderClass.getDeclaredField("classes");
fldClasses.setAccessible(true);
Vector<Class<?>> classesVector= (Vector<Class<?>>) fldClasses.get(classLoader);
for (Class c : classesVector) {
if (c.isAnnotationPresent(annotation)) {
classes.add(c);
}
}
} catch (Exception e) { }
return classes;
}
我通过ServletContext对象从WAR包中获得ClassLoader。如果一个类在WAR和JAR中都定义了注释和相同的名称,那么还有一种保护(您可能应该检查包是否也相同)。
请注意,您可能永远不应该在您自己的项目中使用此代码(可能仅用于调试)。它涉及反映ClassLoader类,使"classes"属性公开。例如,这个属性在Java 9中可能不存在,所以要小心。如果您正在交互由第三方编写的模块,则可能存在一些安全问题。
我有一个类似的问题。您确定已将注释类包含到类路径中吗?如果它们没有被加载,它们会被找到但不会返回并且没有任何异常
reflection库给了我各种各样的问题。现在我正在使用Guava库的反射部分:到目前为止,还没有发生意外行为。在任何情况下,我认为问题的根源是Java类加载器是非常罕见的。也许尝试加载类CustomAnnotation.class之前使用它的反射API。
您的代码应该可以在常规环境下工作。但是,在不同的环境中,比如osgi,您会得到:
1)不同协议的url (bundle/vfs/…)
2)不同的类加载器
在第一种情况下,您应该a)添加相关的UrlType(参见Vfs中的DefaultUrlTypes示例),或者b)使用不同的方法来获取URL(参见ClasspathHelper中的其他方法并检查返回的URL列表)
在第二种情况下,您应该a)将customClassLoader传递给Reflections构造器或ConfigurationBuilder,以便解析发生,或者b)直接查询存储reflections.getStore().get(TypeAnnotationsScanner.class)
参见#8339845,jbosssintegration