在 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://: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://: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 社群所有即將舉行的活動。

檢視全部