在Java中有处理插件的好模式吗?

在Java中有处理插件的好模式吗?,java,plugins,Java,Plugins,这个问题在某种程度上受到了我所问的一个问题的启发 我编写的大多数代码都与API有关,API的本质是易于扩展的。我和我的团队的其他成员都在努力解决如何处理插件的一个常见问题,即可能扩展我们自己的接口的类,在最终实现中应该感觉像是解决方案的原子部分。我特别考虑以下用例(使用汽车类比) 界面: Car 提供的实现: Ford Audi Toyota 第三方实施: Ford Audi Toyota 我们通常要求类CarDealer了解Car的所有现有实现,而不强制第三方在配置文件中显式声明Ca

这个问题在某种程度上受到了我所问的一个问题的启发

我编写的大多数代码都与API有关,API的本质是易于扩展的。我和我的团队的其他成员都在努力解决如何处理插件的一个常见问题,即可能扩展我们自己的接口的类,在最终实现中应该感觉像是解决方案的原子部分。我特别考虑以下用例(使用汽车类比)

界面:

Car
提供的实现:

Ford
Audi
Toyota
第三方实施:

Ford
Audi
Toyota
我们通常要求类
CarDealer
了解
Car
的所有现有实现,而不强制第三方在配置文件中显式声明
Car
。我一直在玩弄的一个想法是让
Car
的实现在
CarDealer
中注册,但这打开了一个新的蠕虫罐头,因为
Toyota
(或任何其他实现)在它们被显式引用之前都不会初始化,这是一个陷阱。注释
Car
的实现,然后检查代码并使用相关注释初始化任何类也是一种方法,但我担心这可能会占用大量资源


我想我们不可能是第一个解决这个问题的人,那么有没有已知的设计模式可以解决这个问题呢?

您可以只为第三方类指定一个位置,然后使用反射来实例化它们


或者编写一个自定义类加载器

看看java.util.ServiceLoader。本质上,您创建了一个接口,然后服务的所有实现者都可以包含一个文件/META-INF/services/在其jar中列出所有实现


然后,可以使用ServiceLoader加载在类路径中发现的所有实现(例如JDBC 4.0要求驱动程序也使用它,以避免使用Class.forName(…)加载驱动程序)。

谈到这种情况时,我想到了两件事:

  • 在抽象实现(或接口)中声明一个名为getName()的方法,在本例中,Toyota将返回“Toyota”,以此类推。然后,您可以考虑扫描整个类路径并收集CAR()的子类。最后,使用(静态?)工厂方法获取所有“汽车实现”或按名称选取它们。使用反射获取新对象

  • 有一个叫做OSGi的平台,它是专门为处理插件(通过使用OSGi服务)而创建的。当使用SpringDM与OSGi通信时,它变得非常容易使用。主要有两种实现:Felix和Equinox


  • 总结一下:如果您可以选择平台,请选择OSGi。如果你不能-我猜你将不得不扫描类路径

    听起来你在找。(好处:维基百科使用了一个汽车示例)

    使用固定位置是我们最终可能得到的结果,但它比我想要的更笨拙。您能否详细说明自定义类加载器的工作原理?请参阅