在 Spring 中使用 Cloud Foundry 服务:第 2 部分 - 自动重新配置

工程 | Ramnivas Laddad | 2011 年 11 月 04 日 | ...

如果您观看了 Cloud Foundry 发布会的视频,您会看到我们部署了从 Spring Web Flow 示例下载的 Spring Travel 应用,为其绑定了 MySQL 服务,并将应用拖放到 STS 中的 Cloud Foundry 服务器上,整个过程没有修改应用本身的代码。这怎么可能呢?因为该应用配置为使用本地数据库。这就是自动重新配置发挥作用的地方。

Cloud Foundry 致力于降低您的初始投入。除了金钱成本,真正的投入在于开发者入门所需花费的时间。自动重新配置是降低您开始使用 Cloud Foundry 时初始投入的一种机制。在这篇博客中,我们将探讨它如何与 Spring 应用一起工作(Grails 应用使用相同的底层机制,因此表现一致)。

利用依赖注入实现自动重新配置

您的应用包含业务逻辑以及与数据库和消息服务等服务的交互。在典型的 Spring 应用中,您利用依赖注入(DI)为使用的每个服务创建 bean,并将这些 bean 注入到需要访问这些服务的其他 bean 中。

让我们来看一个使用关系型数据库的典型 Spring 应用,其中将定义一个数据源 bean,如下所示:


<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/inventory-db"/>
    <property name="username" value="myuser"/>
    <property name="password" value="mypass"/>
</bean>

我们可以将用户名和密码等属性外部化到单独的文件中,但为了重点关注自动重新配置机制,我们将值嵌入在代码中。

然后可以将此 bean 注入到其他 bean 中(在本例中,注入到 JPA 实体管理器中)


<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    <property name="persistenceUnitName" value="persistenceUnit"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

我们可以轻松观察到一点:数据库 URL 指向 localhost 上的数据库,用户名设置为 "myuser",密码设置为 "mypass"。当您将此应用推送到 Cloud Foundry 并绑定 MySQL 或 Postgres 服务时,该服务的 URL 将不会是 jdbc:mysql://localhost:3306/inventory-db,用户名或密码也不会如此简单!因此,如果没有额外的机制,此类应用在启动时会失败。这就是自动重新配置机制发挥作用的地方。自动重新配置机制利用 DI 检查 Spring 应用上下文,查找与服务对应的 bean,并用基于绑定到应用的服务的 bean 替换每个服务。结果是用户应用在本地部署和 Cloud Foundry 中无需任何更改即可工作。

下表显示了自动重新配置会查找哪些 bean 类型进行重新配置。

服务类型替换的 bean 类型
MySQL, Postgresjavax.sql.DataSource
Redisorg.springframework.data.redis.connection.RedisConnectionFactory
MongoDBorg.springframework.data.document.mongodb.MongoDbFactory
RabbitMQorg.springframework.amqp.rabbit.connection.ConnectionFactory

自动重新配置背后的底层机制使用一个 BeanFactoryPostProcessor,它在创建 bean 之前检查应用上下文,并将现有匹配类型的 bean 替换为基于绑定到应用的服务的等效 bean。对于关系型数据库,它还会重新配置 JPA 实体管理器工厂或 Hibernate 会话工厂,以调整使用的方言。

在部署过程中对您的应用进行 staging(阶段性处理)时,Cloud Foundry 会进行两项修改

  1. 它会向您的应用添加一个额外的 jar 包,其中包含 BeanFactoryPostProcessor 和相关资源。请注意,用于自动重新配置的 jar 包也带有一个版本的 cloudfoundry-runtime。但是,这些类通过 shading 机制被重定位到不同的包中。这使得您的应用可以使用不同版本的 cloudfoundry-runtime 而不会发生冲突。
  2. 它会修改 web.xml 以更新构成 Spring 应用上下文的文件,将 BeanFactoryPostProcessor 添加到其中。

限制

服务的自动重新配置仅在以下条件下起作用
  1. 给定服务类型只能有一个服务。例如,您只能将一个关系型数据库服务(MySQL 或 Postgres)绑定到一个应用。
  2. 匹配类型只能有一个 bean。例如,您的应用上下文中只能有一个 DataSource bean。

如果应用不符合这些限制,自动重新配置机制将不会生效。在这些情况下,您将需要使用下一篇博客中描述的 <cloud> 命名空间,无论是否使用 Spring 3.1 profile 支持。

自动重新配置机制适用于典型的 Spring 应用。如果您的应用上下文很复杂,它可能无法工作。在这些情况下,您可以选择退出自动重新配置,我们将在下一节中描述如何操作。

选择退出自动重新配置

在某些情况下,您可能希望选择退出自动重新配置。例如,您可能有一个内存中的关系型数据库,它不应绑定到 Cloud Foundry 服务。Cloud Foundry 提供了几种方法来选择退出自动重新配置机制。
  1. 部署应用时选择框架为 "JavaWeb"。这将把您的应用视为非 Spring 应用。这是一种硬退出方式,您的应用将保持不变(不会向应用添加任何 jar 包,web.xml 也不会改变)。这也意味着本系列博客后续讨论的 profile 功能对此类应用将不可用。
  2. 使用任何创建代表服务的 bean 的 <cloud> 元素。目前这包括 <cloud:data-source><cloud:mongo-db-factory><cloud:rabbit-connection-factory><cloud:redis-connection-factory><cloud:service-scan>。如果应用直接包含基于这些命名空间元素底层类型(例如 CloudMongoDbFactoryBean)的 bean,则退出机制将生效。Cloud Foundry 使用此机制实现退出,因为应用要么希望获得自动重新配置的行为,要么希望完全控制服务创建。我们认为对某些服务进行自动重新配置而对其他服务手动处理没有价值。

结论

Cloud Foundry 中的自动重新配置功能是入门的绝佳方式。随着您的应用成熟或需要绑定到多个服务,您可能需要对服务连接对象进行更精细的控制。这就是 <cloud> 命名空间支持发挥作用的地方。在本系列的下一篇博客中,Thomas Risberg 将解释如何使用它。Thomas,请开始吧。

订阅 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助力您的进步。

了解更多

获取支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单订阅即可获得。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看全部