mff开发者访谈
InfoQ Java的常规撰稿人Alex Blewitt博士最近发布了去年的“ Eclipse 4 Example by Example ”的后续文章,被称为“ Mastering Eclipse Plug-in Development ”,与前一本书一样,基本上都是教程。 ,但是假设您已经熟悉了为Eclipse IDE构建插件的基础知识,并且会快速进入一些相当高级的主题。
前两章探讨了开发人员如何插入Eclipse框架的各个部分,并构建了可与RSS和Atom提要一起使用的新闻阅读器的示例。 第1章使用JFace(构成Eclipse用户界面的一组基于标准窗口小部件工具箱(SWT)的窗口小部件)来创建基本新闻提要向导。 然后将其集成到Common Navigator Framework中,然后由Package Explorer使用它来提供项目内容的树形视图。
第二章介绍Eclipse扩展注册表。 这通常在OSGi运行时中使用,但是作者展示了如何在此环境之外使用它,构建了一个插件,该插件允许其他插件在OSGi或Eclipse运行时之外提供功能。
本书的其余部分主要关注OSGi。 第3章很好地介绍了OSGi服务,而其他Eclipse插件书通常没有介绍这些内容。 OSGi服务可以在运行时具有多个版本,并且可以在其他OSGi环境(例如Felix)中工作。 本章包括对Declarative Services(在OSGi运行时以声明方式实例化服务的原始机制)的很好比较,以及Blueprint,后来又引入了两个次要版本,它们实际上具有相同的作用。
第4章介绍了嵌入在Eclipse 4中并由Felix和Equinox使用的Gogo外壳。 在探究了包括变量,文字和函数的语法之后,作者继续研究如何使用Gogo随附的osgi:addCommand以及编写自定义Java类并将它们注册为OSGi服务来扩展控制台的功能。 然后,第5章研究如何将本机代码加载到OSGi或Eclipse应用程序中,以及如何使用片段捆绑包扩展框架的功能。
第6章很好地介绍了ClassLoader,以及OSGi如何使用类加载器来支持包分离。 由于许多库错误地假设每个JVM只有一个ClassLoader,因此Blewitt还研究了升级这些库的策略,以便它们可以在OSGi环境中运行。
构建Eclipse插件,或者实际上是任何基于OSGi的应用程序,都需要将组件分解成较小的,松散耦合的,高度紧密的模块。 在第7章中,作者介绍了一些常见的技术,设计模式和当前的最佳实践,它们可以帮助完成有时困难的过程。
最后几章介绍了使用OSGi Event Bus构建响应式应用程序,使用Eclipse P2生成更新站点以及如何为Eclipse编写帮助文件。
这本书写得简洁明了,并带有精心选择的示例,这些示例确实有助于读者理解所讨论的各种概念。 本书的大部分内容都很好地介绍了模块化,尤其是Eclipse本身使用的OSGi框架。 它还为类加载提供了出色的介绍。
InfoQ与Alex进行了交谈,以了解有关这本书的更多信息。
InfoQ:您是否一直打算写第一本书的后续书籍?如果没有,那么是什么促使您这么做呢?
亚历克斯:在编写完Eclipse 4 Plug-in Development by Example之后,我打算休息一会儿; 写书要花很多时间,特别是如果您有一份全职工作。 但是,第一本书效果很好,出版商问我是否有兴趣编写一本更高级的书。 我确实有一些要写的想法,尤其是关于OSGi模式的想法,跟进的机会似乎太难了。
由于篇幅和篇幅的问题,有些书本中未涉及。 例如,创建向导来更新站点和帮助文档并不是简单的插件所需要的。 但是,如果您要构建更多的Eclipse插件集或希望其他人能够在这些框架之上构建,那么有必要了解扩展注册表的工作原理以及如何创建自定义扩展点。 还有可能在一本高级书籍中进行更深入的介绍,例如类加载或OSGi服务层。
InfoQ:这本书是OSGi的出色入门,同时也很好地介绍了类加载器。 除了Eclipse插件作者以外,您认为还有其他开发人员会从中受益吗?
亚历克斯: OSGi是过去十年中最被人忽视的技术之一。 对于大型Java服务,它在很多地方,更不用说各种IDE了。 Adobe在OSGi上构建了许多工具,Liferay和Paremus等大型系统正在使用它来为其平台提供动力。 对于每种方式,重点都放在模块化和解耦服务上。 目前,我们开始看到这些方面发生在其他平台中。 这样的例子就是迁移到不同的REST服务的总体趋势。 通过模块化来管理代码复杂性的想法最终是必要的-就像我们所说的那样,即使JDK也正在模块化。 但是模块化的一个副作用是向后兼容,或者至少是版本兼容性。 大多数开发人员都隐式地遵循语义版本控制(有关更多详细信息,请参见http://www.semver.org ),并且不破坏向后兼容客户端的想法是关键。 无论您是构建Java服务还是使用REST服务将许多不同的语言结合在一起,这仍然适用。 如果您不再控制部署单片单元,则必须具备兼容性。 某些语言(例如Scala)将向后兼容性视为付出了高昂的代价,这通常就是为什么您没有像Java那样看到如此多样化的库生态系统的原因。
回到关于OSGi章节的问题-我认为Eclipse专门朝着更多OSGi服务的方向发展,而不是向静态工厂访问器方法发展。 了解OSGi服务模型是了解Eclipse的去向,而不是去往的地方的关键,因此对于Eclipse插件作者来说,这是必读的。 但是,更广泛的Java世界也正在朝着模块化方向发展,向后兼容从未如此重要。 从OSGi模型可以学到很多东西,即使OSGi不是他们以前研究过的东西,也可以使Java开发人员受益。 我希望我已经写了一篇介绍如何使用OSGi完成工作的介绍,而不是对为什么其他人几十年来一直使用它持过多看法。
至于类加载器,即使他们一直透明地使用它们,Java开发人员也常常不了解它们。 一个类加载器提供两种服务: 一种是从一系列字节中创建一个Class(从某个地方加载;无论是本地URL还是远程URL或数据库,甚至是动态生成的),另一种是将Class空间划分为不同的部分。 例如,如果您将两个使用Log4J的Web应用程序部署到Tomcat或Jetty服务器中,则每个Web应用程序将独立加载Log4J类。 因此,在运行时,JVM实际上加载了两个LogFactory类。 第一个对第二个Web应用程序可见,第二个对第二个Web应用程序可见。 即使存在静态引用(例如LoggerFactory.getLogger(Example.class)返回的引用),也将有Logger类的两个实例,每个类加载器均可见。 尽管Java语言使它看起来像是单例,但实际上只有天真的Java开发人员会认为每个JVM只有一个。 例如,这允许不同Web应用程序之间的日志记录级别不同,如果要在共享实例服务器中调试单个应用程序,这将非常有用。 编写类加载器简介的部分原因是为了解释它们的工作原理,因为它们是所有Java应用程序和应用程序服务器如何工作的基础部分(即使不是很明显)。
InfoQ:对我来说,从来都不知道为什么OSGi同时具有声明式服务(在版本4中引入)和蓝图(在版本4.2中引入)–它们似乎或多或少地具有相同的目的。 知道为什么我们都选择了两者吗?
亚历克斯:声明性服务和蓝图都提供了一种自动组装服务和服务依赖项的方法,因此从这个角度看,它们是相似的。 在幕后,两者均使用OSGi服务模型。 他们都在寻找即将到来的服务,并使用它们来动态地重新配置系统。
声明式服务更接近服务运行时的基础。 DS会等到需要某个服务并且其依赖项可用后再发布该服务。 因此,例如,如果您要寻找一个假设的CacheService,则在满足CacheService的依赖项之前它就不存在。 这解决了启动时可能会出现的许多订购问题。 如果在存在支持层之前没有CacheService没有意义,那么您将看不到它。
另一方面,蓝图会在服务实现可用之前发布服务代理。 他们推测性地认为服务会在将来的某个时刻存在,因此请提前发布CacheService。 当客户端第一次尝试使用它时,它然后尝试实例化并满足任何依赖关系。 如果无法满足它们,则会抛出运行时异常。
蓝图的另一个不同之处是,您退回的代理可以传递给各种不同的对象,并作为类的最终成员保留下来。 拥有代理后,即使基础服务来来去去,也将始终使用该代理。 因此,对于不习惯OSGi动态特性的开发人员来说,与不期望服务来去去去的Java代码进行集成会更容易。 蓝图配置也很大程度上基于Spring bean配置文件,这使得从Spring迁移到动态OSGi模型时更容易理解。
因此,正如我在书中所说的那样,如果您事先从Spring环境进行迁移,那么Blueprint模型是一种更容易上手的模型,因为它可以轻松地复制和粘贴Spring配置文件。 如果您不是来自Spring背景,那么DS可能是一种更简单的方法。 但是,在这两种情况下,您都是根据服务的依赖关系来表示服务,并让系统负责实例化和连接,而不是尝试手动完成所有操作。 最终,他们俩都在幕后使用了OSGi服务模型,并且像REST一样,只要服务使用标准API与服务进行通信,服务如何到达那里就无关紧要。
InfoQ:在关于Blueprint的讨论中,您对Gemini有所批评,因为它依赖于Spring,同时指出它对于Spring应用程序开发人员向OSGi的迁移很有用。 我想知道您是否可以对此进行扩展。 OSGi是否提供与Spring类似的功能? 您是否认为Spring的核心实质上是OSGi环境中的传统?
Alex: Gemini和Aries都提供Blueprint服务,就像Jetty和Tomcat都提供Servlet支持一样。 因此,就像采取WAR并将其部署到Jetty或Tomcat一样,您可以将使用Blueprint的OSGi应用程序部署到包含Gemini或Aries的OSGi容器中。 当您考虑等效束时,差异因素之一(考虑所有其他因素)是它们所需的一组依赖关系。 对于Aries,有5个捆绑包(其中两个是SLF4J日志捆绑包)。 对于Gemini,需要安装9个捆绑包,其中6个是Spring捆绑包。 此外,Spring不再使用OSGi元数据构建,因此有必要对存储库中的捆绑包进行后处理才能使用它。
至于Spring是否在OSGi环境中本质上是传统的………有很多基于Spring的优秀项目可以很好地完成工作,并且大多数项目都以某种方式与Spring上下文互操作。 Spring确实普及了依赖注入,并将目标发布从“我如何实例化这个bean”到“请给我这个bean”。 OSGi在服务方面做同样的事情。 关键区别在于该服务可以动态删除,重新启动,升级甚至即时替换。 当然,并不是每个应用程序都需要这种动态性,并且通常以整体方式构建和部署Spring应用程序,因此这实际上取决于最终目标。 尽管OSGi确实很好地发挥了动态性,但有些人可能会发现,对应用程序进行分区和模块化的功能会带来更大的好处。 我想总结一下,是说Spring将您带到了应用程序开发的一个阶段-分离的Bean-但仍然具有部署和配置的整体视图。 OSGi接管了Spring离开的地方,因为它能够动态更新配置并即时进行服务重新配置,而无需停机即可重新启动应用程序。 这在分布式服务可以发挥作用的云或网络环境中特别有用。
我认为,一旦迁移到OSGi平台上,最终有可能使Spring容器不再使用,但是Spring仍然有很多用途。 蓝图可以帮助从Spring过渡到OSGi。 OSGi可能会在平台即服务和云部署中看到大量增长的地方; 可以将一个简单的OSGi应用程序引导到一组复制的分布式服务中。
mff开发者访谈