領先一步
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 都可以在同一個應用程式中支援這兩種風格,從而提供更大的靈活性。例如,欄位注入或基於註解的配置可以輕鬆新增到Blueprint bundle中,就像在傳統的Spring應用程式中一樣,從而補充了Blueprint的功能。
具體來說,讓我們以規範中的一個示例為例,將Blueprint配置與JSR-250(通用註解)以及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*
請注意,模板中沒有關於註解或配置的資訊——由於Bundlor自1.0.0.M6起就支援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列表(透過在Equinox中呼叫ss得到的結果)。
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聯絡我)。