查找实现特定接口的所有类

2022-09-01 01:25:54

我正在开发一个应用程序(Quartz调度程序),其中我们有一个负责实际执行工作的作业类,我们需要在Quartz调度程序中创建触发器时告诉/传递作业类的名称。

我想为所有想要使用API的人提供一个扩展点(除了我将作为API的一部分提供的一些通用作业)。这个想法是创建一个(标记)接口,如果有人想将他们的类声明为调度程序作业类,他们所要做的就是(声明)实现该接口。

我不确定如何找到哪些类遵循协定(通过实现接口),以便我可以向想要在调度程序中调度触发器的用户显示它们。

我的要求不是在运行时加载类,而是显示实现所需接口的类的用户列表,以便用户可以选择类,并且类名可以传递给调度程序。Quartz调度程序最终将负责创建类的实例。

任何人都可以建议我如何实现上述目标,或者有没有其他更好的方法来实现我想要做的事情?

编辑

我浏览了ServiceLoader的文档,似乎要实现服务,必须在META-INF文件夹中创建一个带有实现类名称的文件,这使我认为,如果我的API的用户想要20个不同的实现,他必须在文件中放置20个条目,这对我来说似乎对最终用户来说需要做很多额外的工作,因为每个作业类都会创建用于执行特定作业,并且可以有 100 多个作业类。

如果我的假设是错误的,请纠正我。


答案 1

您可以在这里找到答案。

我可以建议使用 org.reflections

你可以在这里看看它

Reflections reflections = new Reflections("com.mycompany");    
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);

答案 2

我也有类似的需求,我想确保创建的任何实现某个接口的类始终是真正可序列化的。我创建了一个JavaClassFinder,它遍历了类路径中的所有目录,并找到所有可分配给我关心的接口的类。下面是一个代码片段:

public <T> List<Class<? extends T>> findAllMatchingTypes(Class<T> toFind) {
    foundClasses = new ArrayList<Class<?>>();
    List<Class<? extends T>> returnedClasses = new ArrayList<Class<? extends T>>();
    this.toFind = toFind;
    walkClassPath();
    for (Class<?> clazz : foundClasses) {
        returnedClasses.add((Class<? extends T>) clazz);
    }
    return returnedClasses;
}

如果有帮助,我很乐意与您分享代码。唯一的缺点是,这将只处理.class文件 - 我没有添加该功能来解压缩.jars并从那里读取类文件。(但添加它并不是一个巨大的项目。

更新:我检查了上述内容的源代码,发现它依赖于我们标准实用程序库中的许多帮助程序类。为了方便起见,我压缩了所有需要的代码,您可以从JavaClassFinder.zip下载。这将直接在 Eclipse 中设置,您可以获取所需的代码的任何部分。

您将在项目中找到一个名为JavaClassFinderTest.java的JUnit3测试,它向您展示了JavaClassFinder类的功能和用法。运行 Junit 测试所需的唯一外部依赖项是 Junit。

此实用程序的基本用法:

    JavaClassFinder classFinder = new JavaClassFinder();
    List<Class<? extends MyTagInterface>> classes = classFinder.findAllMatchingTypes(MyTagInterface.class);

这将为您提供一个列表,其中包含类路径中可从“MyTagInterface.class”(例如)分配的任何类。希望这有帮助。


推荐