使用Reflections库在Java类路径中查询具有任意属性的类

时间:2012-08-08 21:40:36

标签: java google-reflections

我在过去使用Reflections库来查询具有特定注释的类路径中的类,或者从特定类继承。 这很容易用于反射,因为库已经提供了回答这些特定查询的方法。

例如,下面的代码说明了如何查询从SomeType继承的类和使用SomeAnnotation注释的类,查找位于包my.package.prefix中的类(示例来自文档Reflection.java类):

Reflections reflections = new Reflections("my.package.prefix");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);

但是,在我目前的问题中,我需要做的是查询具有任意属性集的类(例如,特定类名+现有注释的组合+等等)。我不提前知道这些属性,因为它们应该由程序员使用我正在开发的库来定义。

我设想解决方案的一部分就像要求程序员使用布尔方法定义一个策略类,如果类应该在答案集中则回答。

例如,程序员应该实现类似于:

的接口
public interface MyStrategy {
    public boolean match(Class clazz);
}

所以我的问题是,一旦我有了这个策略对象,我怎么能指示Reflections库过滤类,只保留那些根据程序员定义的策略类匹配的类?

更新

显然,过滤部分不是最困难的任务(感谢答案@MvG),但实际上收集了要过滤的所有类(通常是程序员定义的一组基础包中的类)。 所以我的想法是查询所有类,然后使用以下方法过滤它们:     ReflectionUtils.getAll(allClasses, predicate)

然后,为了获得要过滤的初始类集,我尝试查询程序员选择的特定包中Object的所有子类型。

在我用于此的代码下面:

ConfigurationBuilder config = new ConfigurationBuilder();
FilterBuilder fb = new FilterBuilder();
fb.include(FilterBuilder.prefix("my.package.prefix"));
config.filterInputsBy(fb);
config.setUrls(ClasspathHelper.forPackage("my.package.prefix"));
config.setScanners(new SubTypesScanner(false)); //the first argument at the constructor of SubTypesScanner indicates if the Object class should be ignored
Reflections reflections = new Reflections(config);
Set<Class<? extends Object>> unfilteredClasses = reflections.getSubTypesOf(Object.class);

这是最好的(更有效的)解决方案吗?

有人有任何其他想法吗?提前谢谢!

1 个答案:

答案 0 :(得分:1)

使用com.google.common.base.Predicate表达您的策略,或将您自己的策略对象包装到此类谓词中。然后你可以写

ReflectionUtils.getAll(allClasses, predicate);

似乎实际上计算这个allClasses可迭代的任务将是更艰巨的任务。我乍一看没有简单的API。您可能必须直接访问底层存储,并自己将类名转换为Class个对象。这意味着加载所有类,这可能非常耗时,甚至可能在某些情况下失败。