我怎样才能在Java中以编程方式获得所有接口实现的列表?

我可以用reflection或类似的东西吗?

埃里克森说了什么,但是如果你仍然想这样做,那么看看思考 。 从他们的页面:

使用reflection,您可以查询您的元数据:

  • 获取某种types的所有子types
  • 得到所有types的注释与一些注释
  • 获取所有types的注释,包括注释参数匹配
  • 得到所有的方法用一些注释

一般来说,这样做很昂贵。 要使用reflection,类必须被加载。 如果要加载类path中的每个类,则需要时间和内存,不build议使用。

如果你想避免这种情况,你需要实现你自己的类文件parsing器,而不是reflection操作,效率更高。 一个字节码工程库可能有助于这种方法。

服务提供者机制是枚举可插入服务实现的常规手段。 在Java 6中使用ServiceLoader ,或者在早期版本中实现自己的。 我在另一个答案中提供了一个例子 。

我一直在寻找一段时间,似乎有不同的方法,这里是一个总结:

  1. reflection库是相当受欢迎的,如果你不介意添加依赖项。 它看起来像这样:

     Reflections reflections = new Reflections("firstdeveloper.examples.reflections"); Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class); 
  2. ServiceLoader (按照erickson的答案),它看起来像这样:

     ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class); for (Pet implClass : loader) { System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat } 

    请注意,为了这个工作,您需要将Pet定义为ServiceProviderInterface(SPI)并声明它的实现。 您可以通过在名为examples.reflections.Pet resources/META-INF/services创build一个文件并在其中声明Pet所有实现

     examples.reflections.Dog examples.reflections.Cat 
  3. 包级别注释 。 这里是一个例子:

     Package[] packages = Package.getPackages(); for (Package p : packages) { MyPackageAnnotation annotation = p.getAnnotation(MyPackageAnnotation.class); if (annotation != null) { Class<?>[] implementations = annotation.implementationsOfPet(); for (Class<?> impl : implementations) { System.out.println(impl.getSimpleName()); } } } 

    和注释定义:

     @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PACKAGE) public @interface MyPackageAnnotation { Class<?>[] implementationsOfPet() default {}; } 

    并且必须在该包内的一个名为package-info.java的文件中声明包级注释。 这里是样本内容:

     @MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class}) package examples.reflections; 

    请注意,此时只有ClassLoader已知的包将通过对Package.getPackages()的调用加载。

另外,还有其他一些基于URLClassLoader的方法,它们总是被限制在已经加载的类中,除非你做一个基于目录的search。

是的,第一步是确定你所关心的所有课程。 如果你已经有这个信息,你可以通过它们中的每一个枚举并使用instanceof来validation关系。 相关文章在这里: http : //www.javaworld.com/javaworld/javatips/jw-javatip113.html

埃里克森说的是最好的。 这是一个相关的问题和答案的线程 – http://www.velocityreviews.com/forums/t137693-find-all-implementing-classes-in-classpath.html

Apache BCEL库允许您在不加载的情况下阅读课程。 我相信它会更快,因为你应该可以跳过validation步骤。 使用类加载器加载所有类的另一个问题是,您将遭受巨大的内存影响,以及无意中运行您可能不想做的任何静态代码块。

Apache BCEL库链接 – http://jakarta.apache.org/bcel/

另外,如果您正在编写一个IDE插件(您正在尝试执行的操作相对普遍),那么IDE通常会为您提供更有效的方式来访问用户代码当前状态的类层次结构。

Spring有一个非常简单的方法来达到这个目的:

 public interface ITask { void doStuff(); } @Component public class MyTask implements ITask { public void doStuff(); } 

然后你可以自动ITask一个ITasktypes的列表,Spring将会用所有的实现来填充它:

 @Service public class TaskService { @Autowired private List<ITask> tasks; } 

我遇到了同样的问题。 我的解决scheme是使用reflection来检查ObjectFactory类中的所有方法,消除那些不是返回一个绑定POJO的实例的createXXX()方法的方法。 如此发现的每个类都被添加到一个Class []数组,然后传递给JAXBContext实例化调用。 这performance的很好,只需要加载即将被需要的ObjectFactory类。 我只需要维护ObjectFactory类,一个手工执行的任务(在我的情况下,因为我开始使用POJO和使用schemagen),或者可以根据需要由xjc生成。 无论哪种方式,它是高性能,简单,有效的。