【问题标题】:Are there any good patterns for handling plugins in Java?在 Java 中处理插件有什么好的模式吗?
【发布时间】:2011-10-28 22:47:13
【问题描述】:

这个问题的灵感来自我问过的previous question

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

界面:

Car

提供的实现:

Ford
Audi

第三方实施:

Toyota

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

我认为我们不可能是第一个遇到这个问题的人,那么有什么已知的设计模式可以解决这个问题吗?

【问题讨论】:

标签: java plugins


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我们最终可能会使用固定位置,但它比我想要的要笨拙。您能否详细说明自定义类加载器的工作原理?
    【解决方案3】:

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

    1. 在您的抽象实现(或接口)中声明一个名为 getName() 的方法,在这种情况下,Toyota 将返回“Toyota”,依此类推。然后你可以考虑扫描整个类路径并收集 Car 的子类 (use this method for that)。最后使用(静态?)工厂方法来获取所有“汽车实现”或按名称选择它们。使用反射获取新对象。

    2. 有一个名为 OSGi 的平台,专门用于处理插件(通过使用 OSGi 服务)。当使用 Spring DM 与 OSGi 进行通信时,它变得非常容易使用。有 2 个主要实现:Felix 和 Equinox。

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

    【讨论】:

      【解决方案4】:

      听起来您正在寻找Dependency Injection。 (奖励:维基百科使用汽车示例)

      【讨论】:

        猜你喜欢
        • 2018-01-11
        • 2014-02-25
        • 2012-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-18
        • 2013-12-31
        • 2019-08-25
        相关资源
        最近更新 更多