反射返回集与空元素



我使用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

相关内容

  • 没有找到相关文章