領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多上個月,在最初的 4.0 版本釋出近 4 年後,OSGi 聯盟正式批准了 OSGi 服務平臺 4.2 版本。公告的標題突出了 Blueprint Container 服務,這是 Compendium 規範的新增內容,基於 Spring Dynamic Modules(也稱為 Spring OSGi)專案推廣的程式設計模型。為了快速總結 Blueprint,我將直接引用 OSGi 規範中的一段話:
(Blueprint Container)[...] 定義了一個依賴注入框架,專用於 OSGi bundle,它理解服務的獨特動態性。它提供了一種 OSGi bundle 程式設計模型,該模型具有最少的實現依賴性,並且 Java 程式碼中幾乎沒有意外的複雜性。
熟悉 IoC 概念或 Spring 及 Spring DM 配置的使用者會發現 Blueprint 規範易於理解。事實上,由於它派生自 Spring DM,許多 Blueprint 概念、語法和術語都是相同的,在大多數情況下,在兩者之間移植現有應用程式只需調整配置檔案即可。在功能方面,Blueprint 提供了一個控制反轉容器,支援建構函式注入和 Setter 注入、工廠方法、生命週期管理和回撥、簽名消歧以及型別轉換等功能。在 OSGi 方面,可以使用匯出器(exporters)和匯入器(importers)來透明地釋出和消費 OSGi 服務。
下面是一個 Blueprint 配置的程式碼片段,它建立了幾個物件,匯入了一個服務,將它們連線在一起,然後將目標作為 OSGi 服務暴露出來:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
<!-- basic object creation -->
<bean id="object" class="java.lang.Object"/>
<bean id="length" class="java.lang.Integer">
<argument value="4"/>
</bean>
<bean id="buffer" class="java.lang.StringBuffer" depends-on="simple">
<property name="length" ref="length"/>
</bean>
<bean id="current-time" class="java.lang.System" factory-method="currentTimeMillis" scope="prototype"/>
<bean id="list" class="java.util.ArrayList" destroy-method="clear" activation="eager">
<argument ref="length"/>
</bean>
<!-- service import -->
<reference id="ds" class="javax.sql.DataSource" filter="(batch-size=200)"/>
<bean id="consumer" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<property name="dataSource" ref="ds"/>
</bean>
<!-- service export -->
<service id="publisher" ref="consumer" auto-detect="interfaces"/>
</blueprint>
除了配置之外,Blueprint 還提供了一個小型的 API(透過 container 和 reflect 包)用於依賴查詢、讀取元資料或執行自定義型別轉換,這在一定程度上類似於 Spring。有關 Blueprint 和 Spring DM 之間相似性(和差異性)的更多資訊,請參閱 DM 2.0 M1 參考文件中的專門章節。
值得指出的是,儘管 Blueprint 依賴於 OSGi 4.2 API,但 Spring DM 2.x 不依賴。執行 OSGi 4.0 和 4.1 的使用者可以安全地使用 Spring DM 2.x;只有 Blueprint 功能會被停用,其餘功能仍然可用。
使用 Spring DM 的主要優勢之一是,可以從 OSGi 透明地完全訪問 Spring 容器:無論您打算使用 Blueprint、Spring/Spring DM API 和配置,Spring DM 2.x 都可以在同一個應用程式中同時支援這兩種風格,從而提供更大的靈活性。例如,就像在傳統的 Spring 應用程式中一樣,可以輕鬆地向 Blueprint bundle 新增欄位注入或基於註解的配置,從而補充 Blueprint 的功能。
為了說明這一點,讓我們來看一個規範示例,並將 Blueprint 配置與 JSR-250(Common Annotations)以及 Spring 3 中的一些新增功能(例如 JSR-330(Java 依賴注入)支援)結合起來。
public interface Echo {
public String echo(String m);
}
public class EchoImpl implements Echo {
String message;
public void setMessage(String m) {
this.message= m;
}
public String echo(String s) { return message + s; }
}
<blueprint>
<service id="echoService" interface="com.acme.Echo" ref="echo"/>
<bean id="echo" class="com.acme.EchoImpl"
<property name="message" value="Echo: "/>
</bean>
</blueprint>
我將在這個示例中使用 Maven,並遵循其專案佈局約定:[caption id="attachment_2939" align="aligncenter" width="326"][/caption]
public class EchoImpl implements Echo {
@Inject
private PackageAdmin pkgAdmin;
String message;
public void setMessage(String m) {
this.message = m;
}
public String echo(String s) {
return message + s;
}
@PostConstruct
void startup() {
Bundle bnd = pkgAdmin.getBundle(getClass());
ExportedPackage pkg = pkgAdmin.getExportedPackage(Echo.class.getPackage().getName());
System.out.printf("Echo service bundle [%s] wired to bundles %s\n", bnd.getSymbolicName(),
Arrays.toString(pkg.getImportingBundles()));
}
}
<blueprint>
<service id="echoService" interface="com.acme.Echo" ref="echo" />
<bean id="echo" class="com.acme.internal.EchoImpl">
<property name="message" value="Echo: "/>
</bean>
<reference id="pkgAdmin"
interface="org.osgi.service.packageadmin.PackageAdmin" />
<context:annotation-config/>
</blueprint>
Excluded-Exports: *.internal*
注意,模板不包含關於註解或配置的任何資訊——自 1.0.0.M6 版本以來,Bundlor 能夠理解 Blueprint bundle,它會自動拾取並解析任何相關的配置和類。
# mvn package
大功告成。現在讓我們執行示例。
Manifest-Version: 1.0
Export-Package: com.acme;version="0.0.0"
Bundle-Name: blueprint-atinject
Bundle-ManifestVersion: 2
Bundle-SymbolicName: blueprint-atinject
Import-Package: javax.annotation,javax.inject,org.osgi.framework,org.o
sgi.service.packageadmin
只需將生成的 jar 部署到 OSGi 4.2 框架中,同時部署 Spring DM 2.0.0.M1,您應該會看到以下輸出:
INFO: Blueprint API detected; enabling Blueprint Container functionality
...
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
...
Echo service bundle [blueprint-atinject] wired to bundles []
...
INFO: Publishing service under classes [{com.acme.Echo}]
下面是我的 OSGi bundle 列表(透過呼叫ss命令在 equinox 中生成)。
0 ACTIVE org.eclipse.osgi_3.5.0.v20090520
1 ACTIVE com.springsource.slf4j.api_1.5.6
Fragments=2
2 RESOLVED com.springsource.slf4j.juli_1.5.6
Master=1
3 ACTIVE com.springsource.slf4j.org.apache.commons.logging_1.5.6
4 ACTIVE com.springsource.org.aopalliance_1.0.0
5 ACTIVE com.springsource.net.sf.cglib_2.1.3
6 ACTIVE org.springframework.asm_3.0.0.RC1
7 ACTIVE org.springframework.expression_3.0.0.RC1
8 ACTIVE org.springframework.core_3.0.0.RC1
9 ACTIVE org.springframework.beans_3.0.0.RC1
10 ACTIVE org.springframework.aop_3.0.0.RC1
11 ACTIVE org.springframework.context_3.0.0.RC1
12 ACTIVE org.springframework.osgi.io_2.0.0.M1
13 ACTIVE org.springframework.osgi.core_2.0.0.M1
14 ACTIVE org.springframework.osgi.extender_2.0.0.M1
15 ACTIVE com.springsource.javax.inject_0.9.0.PFD
16 ACTIVE com.springsource.javax.annotation_1.0.0
17 ACTIVE blueprint-atinject_0.0.0
您可以在此處找到專案檔案(包含說明)。
透過在 OSGi 平臺內採用事實標準(例如依賴注入),我們相信 Blueprint 對 OSGi 和非 OSGi 開發人員都有益,因為它鼓勵 API 解耦和基礎設施關注點的外部化,顯著降低了建立和配置 OSGi 應用程式的入門門檻。
我們對未來的發展和當前正在開發的功能感到非常興奮!
要獲取有關 OSGi 和 Spring DM 的更多更新(和反饋!),請關注我們的部落格和 Twitter(透過標籤 #osgi、#springdm、#dmserver。本人在 @costinl 可用)。