实现企业集成模式第 0 部分
在我关于 Spring Integration 的演讲之后,我收到了很多关于澄清和示例的问题。为了满足需求,我将开始一个关于使用 Spring Integration 实现不同集成模式的小系列文章。本文将重点介绍基础知识。它将向您展示如何开始并运行,以及逐步完成其中一个示例。
如果您以前从未听说过 Spring Integration,那么最好阅读Mark Fisher 撰写的介绍性博客或浏览项目网站以熟悉它。一般来说
让我先声明一下:...
在我关于 Spring Integration 的演讲之后,我收到了很多关于澄清和示例的问题。为了满足需求,我将开始一个关于使用 Spring Integration 实现不同集成模式的小系列文章。本文将重点介绍基础知识。它将向您展示如何开始并运行,以及逐步完成其中一个示例。
如果您以前从未听说过 Spring Integration,那么最好阅读Mark Fisher 撰写的介绍性博客或浏览项目网站以熟悉它。一般来说
让我先声明一下:...
尊敬的 Spring 社区:
我们很高兴地宣布 Spring Web Flow 2 正式发布。下载 | 文档
Spring Web Flow 是 Spring 产品组合中专注于提供构建和运行富 Web 应用程序的基础设施的项目。作为一个 Spring 项目,Web Flow 基于 Spring Web MVC 框架提供
Web Flow 2 发行版中的模块及其与 Spring Framework 的关系如下所示
Spring Web MVC 框架(Spring Framework 发行版中的一个模块)为使用经过验证的 ModelViewController 范式使用 Spring 开发 Web 应用程序提供了基础。Web Flow 发行版中的每个模块都建立在此基础之上。
Web Flow 模块是 MVC 扩展,允许您使用领域特定语言定义控制器。此语言旨在模拟需要多个请求到服务器才能完成的用户交互,或者可能从不同上下文中调用。
Spring JavaScript 是一个 JavaScript 抽象框架,它使编写不显眼的 JavaScript 变得很容易,从而通过行为逐步增强网页。该框架由一个公共 JavaScript API 以及一个基于 Dojo Toolkit 的实现组成。Spring.js 旨在简化 Dojo 在常见企业场景中的使用,同时保留其在高级用例中的全部功能。
Spring JavaScript 可以与任何服务器端框架一起使用。Web Flow 2 发行版包括 Spring JavaScript 和 Spring Web MVC 之间的便捷集成,用于处理 Ajax 请求。
该Spring Faces模块包含 Spring 对 JavaServerFaces 的支持。此支持允许您在熟悉的 Spring MVC 和 Web Flow 控制器环境中使用 JSF 作为视图技术。通过这种架构方法,您可以结合 JSF UI 组件模型的优势和 Web MVC 架构的优势。Spring Faces 还包括一个基于 Spring JavaScript 的轻量级组件库,用于以渐进的方式声明性地启用 Ajax 和客户端验证行为。
除了引入新的 Spring Faces 和 Spring Javascript 模块外,Web Flow 2 发布工作还解决了两个主要主题:集成和简洁性。
在每个模块中,Web Flow 2 发行版都添加了许多有趣的集成,允许您丰富您的 Web 应用程序。这些集成支持
Web Flow 2 中的流定义语言得到了极大的简化,同时整体功能也变得更加强大。这些简化包括
InfoQ 有一个讨论主题,总结了对 SpringSource Application Plaform 发布的反应。Michael Burke 在该主题上提出了一个很好的问题,可以将其概括为“忘记围绕 OSGi 的炒作,如果我将当前打包为 EAR 的应用程序移植到 OSGi 捆绑包,我可以期望看到哪些好处?”
我开始在 InfoQ 主题上回答这个问题,但我的答案对于评论来说太长了,所以我将在本文中解决它。
这是一个很好的问题。在基于 OSGi 的应用程序与传统的基于 JEE EAR 的应用程序之间,您将看到的最大区别是模块化的改进。因此,问题就变成了,这种改进的模块化是否会给我带来任何好处,如果是,它们是什么?这本书“设计规则,模块化的力量”对这个问题进行了非常全面的论述。这是一个很好的背景,但我有一种感觉,迈克尔可能正在寻找一些比你在那本书中找到的东西更不那么理论化的东西……
SpringSource Application Platform 的主要优势之一是它能够根据需要提供依赖项。这样做的好处是双重的:它确保平台的内存占用尽可能小,并允许应用程序部署而无需将所有依赖项封装在一个单一的部署单元(例如 WAR 文件)中。要利用这些功能,您需要了解平台的供应存储库,本博客旨在提供这些信息。
当平台启动部署的应用程序时,其…
很高兴听到关于 SpringSource Application Platform 的大量讨论,无论是在线还是在 JavaOne 的现场。WebSphere 事务架构师 Ian Robinson 提供了最具洞察力的 评论 之一
这是否会影响 WebSphere?好吧,Spring 框架的核心没有任何变化。无论 SpringSource Application Platform 的未来如何,Spring 框架核心项目都将继续与 WebSphere 互补。就像炸鱼薯条一样。Ian 完全正确。SpringSource Application Platform 是 Spring 部署的另一种选择。在…中没有任何变化。
SpringSource Application Platform 由 OSGi 捆绑包构建,并支持也由 OSGi 捆绑包构建的应用程序。平台支持 OSGi 的标准功能,但也支持一些其他清单头。一些人询问了 为什么 SpringSource 添加了专有头?
和 新头的语义是什么?
,因此这篇文章解释了背景动机以及 Import-Library 和 Import-Bundle 的语义。
因此,精通 OSGi 的开发人员可以使用平台作为标准 OSGi 容器,并受益于平台功能,例如
好吧,该过程中的某些步骤相对容易,尤其是在遵循良好的软件工程实践并将代码组织成服务、域和基础架构组件的情况下。这些组件可以转换为捆绑包,并且它们之间的依赖关系可以使用 META-INF/MANIFEST.MF 中的标准 OSGi Import-Package 和 Export-Package 头来表达。
更困难的一步是表达对企业框架(如 Spring 和 Hibernate)的依赖关系。完全可以使用标准 OSGi Import-Package 和 Require-Bundle 头来表达这些依赖关系,如果您希望创建将在其他 OSGi 容器中运行的 OSGi 捆绑包,这正是您应该做的,但这种方法有一些隐藏的成本。
首先,开发人员必须准确确定哪些包构成给定的框架。仅导入应用程序代码使用的包是不够的,因为当加载应用程序时,几个企业框架会将更多依赖项编织到应用程序的字节码中。开发人员必须发现(可能通过反复试验)要导入哪些其他实现包以确保编织应用程序的正确行为。
然后是将框架从一个版本迁移到下一个版本的琐事,其中构成框架的精确包集已更改。编织所需的额外包通常不由公共合同定义,因此可能会发生更改。
此外,生成的包导入没有正确捕获设计意图,这使得将来维护或扩展应用程序更加困难。
我们真的不想给我们的用户带来这些负担,因此我们创建了一些其他 SpringSource Application Platform 特定的清单头,Import-Library 和 Import-Bundle,作为表达对企业框架依赖关系的便捷方法。如下所示,这些头实际上只是 语法糖
,它们用标准 OSGi 包导入来表达。
Import-Library: <librarySymbolicName>;version=<versionRange>其中 <librarySymbolicName> 是库的
符号名称,<versionRange> 是使用 OSGi 版本范围表示法表示的可接受库版本的范围。库定义指定库的符号名称和版本,这两者共同唯一地标识平台的库。
如果您不熟悉 OSGi 版本范围表示法,到目前为止最常用的形式是最小版本范围,例如 2
,表示 版本 2 或更高版本
,以及 半开
范围,例如 [2.2.1,2.2.2)
,表示 2.2.1(含)到 2.2.2(不含)之间的任何版本。如果省略 version=<versionRange>(当然还有分号分隔符),则默认范围包括所有版本。
对于每个库导入,平台都会选择具有给定符号名称和平台存储库中提供的给定版本范围内的最高版本的库。然后,平台将库导入替换为一组包导入,这些导入与库的捆绑包导出的所有包匹配。平台检测到捆绑包导入两个或多个导出公共包的库的情况,发出相应的日志消息,并无法安装导入捆绑包。
例如,以下标题导入 Spring Framework 库 的某个版本,该版本介于 2.5.4(含)和 2.5.5(不含)之间
Import-Library: org.springframework.spring;version="[2.5.4,2.5.5)"
:=分隔符,它指示修改清单头语义的
指令,而不是
=分隔符,它指示
匹配属性,如 version。
Import-Library: <librarySymbolicName>;version=<versionRange>;resolution:=optional
如果未指定 resolution,或将其指定为 mandatory,则如果不存在具有给定符号名称和给定范围内的版本的库,则包含导入库头的捆绑包将无法安装。但是,如果指定了 resolution:=optional,则如果找不到合适的库,则将忽略库导入。
例如,以下标题导入 2.5 及更高版本的 Spring Framework 库,但如果找不到合适的库,则将被忽略
Import-Library: org.springframework.spring;version="2.5";resolution:=optional
Import-Library: org.foo.p;version="[1,2)",org.bar.q;version="[2,3)"
如您所料,对于每个导入的捆绑包,平台都会选择具有给定符号名称和平台存储库中提供的给定版本范围内的最高版本的捆绑包。然后,平台将捆绑包导入替换为一组包导入,这些导入与捆绑包导出的包匹配。
例如,以下标题导入 Hibernate Object-Relational Mapper 捆绑包
Import-Bundle: com.springsource.org.hibernate;version="[3.2.6,3.2.7)"
好吧,我们希望 Require-Bundle 保留其标准语义,包括能够将拆分包的各个部分组合在一起的能力。但我们希望 Import-Library 和 Import-Bundle 与 Import-Package 具有相同的底层语义,从而避免了拆分包的复杂性。
我们还预计,随着平台的不断发展,我们将需要向 Import-Library 和 Import-Bundle 添加更多指令,这些指令不适合添加到 Require-Bundle 中。
对于希望利用平台头文件,但需要生成可在其他 OSGi 容器上运行的 Bundle 的用户,我们计划开发一个工具,该工具将替换 Import-Library 和 Import-Bundle…
自从我们上周三发布 SpringSource 应用平台以来,许多开发人员已经下载了 1.0.0 Beta 版,并开始试用该平台。因此,人们开始询问:“如何将我的应用程序部署到平台上,以及我有哪些部署和打包选项?” 此外,开发人员迫切希望看到工作示例。作为回应,S2AP 团队将在未来几周内发布几个示例应用程序,演示这些功能以及更多功能,但在您获得这些示例之前,我想先向您提供高级别的……
尊敬的 Spring 社区:
我很高兴地宣布 Spring Web Services 1.5.1 已经发布!
这是 Spring-WS 1.5 系列中的第一个错误修复和增强版本。它修复了自 1.5.0 以来报告的所有错误,并在整个框架中引入了各种增强功能。
以及更多。请参阅变更日志以了解详细信息。
请注意,由于向后兼容性问题,CastorMarshaller 现在需要 Castor 1.2 或更高版本。
此致,
Arjen Poutsma
Spring Web Services 负责人
许多人一直在询问 SpringSource 应用平台究竟为 Spring 应用程序做了什么,才能使它们在 OSGi 下良好运行,以及除了 OSGi 和 Spring Dynamic Modules 开箱即用提供的功能之外,还提供了哪些功能。Adrian 昨天的帖子强调了一些一般问题,现在让我们看看一些细节。
在 OSGi 上运行 Spring 应用程序最具挑战性的三个方面是
其余不太重要的问题包括:JSP 支持、TLD 扫描、注释匹配和资源查找。总的来说,需要解决大量问题才能使应用程序顺利部署。
加载时织入是在健壮的方式下支持的最具问题性的功能之一。在基本层面上,它需要挂接到 Equinox 的 ClassLoader,以便可以在 defineClass 调用期间附加和使用标准的 ClassFileTransformers。最重要的是,LTW 的许多用法都需要访问一个一次性 ClassLoader,该加载器可用于检查类型以确定在织入过程中需要发生什么,而不会影响真实的 ClassLoader。
实际上,这种基本级别的支持实现起来相当简单。困难在于,当织入由一个 Bundle 中的类驱动,但另一个 Bundle 中的类需要被织入时。这在企业应用程序中非常常见,其中一个 Bundle 包含域实体,另一个 Bundle 包含使用 JPA EntityManager 的类型。平台通过确保应用程序中的所有 Bundle 都可以使用相应的 ClassFileTransformers 进行织入来处理这种复杂性。
当您开始将织入传播到其他 Bundle 时,您确实需要知道何时停止。如果您只是将织入应用于所有 Bundle,那么应用程序将相互干扰。平台通过显式地对织入进行范围限定来防止这种情况发生,以便它仅应用于应用程序中的模块。
LTW 的另一个问题是它使刷新变得复杂。当一个 Bundle 刷新时,OSGi 将刷新所有依赖它的 Bundle。这意味着,在我上面给出的示例中,刷新域 Bundle 将导致 EntityManager Bundle 刷新。但是,刷新 EntityManager **不会**刷新域 Bundle,这意味着织入可能不同步。平台通过将刷新传播到受织入影响的其他 Bundle 来处理此问题。
对于类路径扫描,主要问题是 Equinox 不会公开标准的 jar: 和 file: 资源。平台在中间放置一个适配器,以便库可以看到它们期望的资源协议。这有一个很好的副作用,可以使 **很多** 第三方库工作 - 它不仅仅是针对类路径扫描的修复。
许多第三方库使用线程上下文 ClassLoader 来访问应用程序类型和资源。OSGi 中的每个 Bundle 都有自己的 ClassLoader,因此,任何时候都只能公开一个 Bundle 作为线程上下文 ClassLoader。这意味着,如果第三方库需要查看分布在多个 Bundle 中的类型,它将无法按预期工作。
平台通过创建一个 ClassLoader 来解决此问题,该加载器导入应用程序中每个模块的所有导出的包。然后将此 ClassLoader 公开为线程上下文 ClassLoader,使第三方库能够查看应用程序中所有导出的类型。
这只是平台解决的问题的一小部分,但希望它能让你了解平台对 Spring 框架用户意味着什么。