开放的扩展使许多应用程序受益。 这篇文章描述了两种在Java中实现这种可扩展性的方法。
可扩展的应用
可扩展应用程序是可以扩展其功能而不必重新编译它们 ,有时甚至不必重新启动它们的应用程序。 只需将jar添加到类路径中,或通过更复杂的安装过程来实现。
Eclipse IDE是可扩展应用程序的一个示例。 它允许安装称为插件的扩展,以便可以使用新功能。 例如,您可以安装源代码管理(SCM)插件以与您喜欢的SCM一起使用。
再举一个例子,设想一个实现了的XACML规范授权 。 XACML中的“ X”代表“可扩展”,并且规范定义了许多扩展点 ,例如属性和类别ID,结合了算法,功能和策略信息点。 良好的XACML实现将允许您通过提供实现扩展点的模块来扩展产品。
服务提供商接口
Oracle用于创建可扩展应用程序的解决方案是服务提供商接口 (SPI)。
在这种方法中,扩展点由接口定义:
package com.company.application;public interface MyService {// ...
}
您可以使用ServiceLoader类找到此类扩展点的所有扩展:
public class Client {public void useService() {Iterator<MyService> services = ServiceLoader.load(MyService.class).iterator();while (services.hasNext()) {MyService service = services.next();// ... use service ...}}
此扩展点的扩展可以是实现该接口的任何类:
package com.company.application.impl;public class MyServiceImpl implements MyService {// ...
}
实现类必须是公共可用的,并且具有公共的无参数构造函数。 但是,这对于ServiceLoader
类来说还远远不够。
您还必须在META-INF/services
创建一个以扩展点接口的标准名称命名的文件。 在我们的示例中,将是:
META-INF/services/com.company.application.Myservice
此文件必须是UTF-8编码的,否则ServiceLoader
将无法读取它。 该文件的每一行都应包含实现扩展点的一个扩展的全限定名称,例如:
com.company.application.impl.MyServiceImpl
OSGi服务
仅当扩展点文件位于类路径上时,上述SPI方法才有效。
在OSGi环境中,情况并非如此。 幸运的是,OSGi对于扩展性问题有自己的解决方案: OSGi服务 。
借助Declarative Services ,OSGi服务易于实现,尤其是在使用Apache Felix 服务组件运行时 (SCR)的注释 时 :
@Service
@Component
public class MyServiceImpl implements MyService {// ...
}
使用OSGi和SCR,使用服务也非常容易:
@Component
public class Client {@Referenceprivate MyService myService;protected void bindMyService(MyService bound) {myService = bound;}protected void unbindMyService(MyService bound) {if (myService == bound) {myService = null;}}public void useService() {// ... use myService ...}}
两全其美
那么,您应该选择两个选项中的哪个? 当然,这取决于您的情况。 在OSGi环境中,显然应该选择OSGi服务。 如果您不在OSGi环境中,则无法使用它们,因此只剩下SPI。
但是,如果您正在编写框架或库,却又不知道您的代码是否将在基于OSGi或类路径的环境中使用,该怎么办?
您将希望尽可能多地使用您的库,因此最好是同时支持这两种模型。 如果您要小心,可以这样做。
请注意,将像OSGI-INF/myServiceComponent.xml
这样的Declarative Services服务组件文件添加到jar中(这是SCR注释在处理时最终会完成的工作)仅在OSGi环境中有效,但在OSGi外部无害。
同样,SPI服务文件将在传统的类路径环境中工作,但在OSGi中是无害的。
因此,这两种方法实际上是互斥的,并且在任何给定的环境中,这两种方法中只有一种会找到任何东西。 因此,您可以编写使用这两种方法的代码。 这有点重复,但是它允许您的代码在两种类型的环境中都能工作,因此您也可以吃蛋糕。
参考: 如何从安全软件开发博客上的JCG合作伙伴 Remon Sinnema 创建可扩展Java应用程序 。
翻译自: https://www.javacodegeeks.com/2012/12/how-to-create-extensible-java-applications.html